Linux利用socket实现两台pc之间的数据传输功能,包括windows到linux,UDP实现
makefile 和TCP一样,参见上一篇博文客户端和服务端主函数也和上一篇的tcp是一样的,同样参考上一篇博文,这里只是修改了pub.c的文件了#ifdef WIN#include#else#include#include#include#include#include#include#define SOCKET int#endif#incl
·
makefile 和TCP一样,参见上一篇博文
客户端和服务端主函数也和上一篇的tcp是一样的,同样参考上一篇博文,这里只是修改了pub.c的文件了
/*
* pub.c
*
* Created on: 2016年7月14日
* Author: Administrator
*/
#ifdef WIN
#include <WinSock2.h>
#else
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#define SOCKET int
#endif
#include <stdio.h>
#include "pub.h"
#define BUFSIZE 262144 //1024 * 256
void getfilename(const char *filename, char *name)
{
int len = strlen(filename);
int i;
for (i = (len - 1); i >= 0; i--)
{
if ((filename[i] == '\\') || (filename[i] == '/'))
{
break;
}
}
strcpy(name, &filename[i + 1]);
}
int init_socket()
{
// 如果是windows,执行如下代码
#ifdef WIN
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return -1;
}
#endif
return 0;
}
SOCKET create_send_socket()// 建立發送數據的udp socket
{
if (init_socket() == -1)
return 0;
SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);// 建立UDP socket
if (st == 0)
return 0; // 如果建立socket失敗,返回0
return st; // udp socket建立成功,返回socket描述符
}
SOCKET create_recv_socket(int port)
{
SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);// 建立UDP socket
if (st == 0)
return 0;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(st, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
printf("bind failed %s\n", strerror(errno));
return 0;
}
return st;// udp
}
// 连接到hostname指定的IP地址和port指定的端口号
int send_work(const char *hostname, int port, const char *filename)
{
SOCKET st_send = create_send_socket();// 建立发送数据的UDP Socket
SOCKET st_recv = create_recv_socket(port + 1);// 建立接受数据的UDP Socket
if (st_send == 0) // 建立失败,函数返回
{
return 0;
}
if (st_recv == 0) // 建立失败,函数返回
{
return 0;
}
FILE *fd = fopen(filename, "rb"); // 以只读方式打开filename指定的文件
if (fd == NULL) // 如果打开文件失败,函数返回
{
printf("open %s failed %s\n", filename, strerror(errno));
return 0;
}
char *buf = malloc(BUFSIZE); // 申请一个缓冲区,存放接收到的文件内容
memset(buf, 0, BUFSIZE);
// 从完整路径名中解析出文件名称
getfilename(filename, buf);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(hostname);
// 客戶端第一次給server端發送文件名
size_t rc = sendto(st_send, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)); // 客户端第一次给server端发送的数据为要传递的文件名
if (rc <= 0)
{
printf("send failed %s\n", strerror(errno));
}
else
{
struct sockaddr_in client_addr;
#ifdef WIN
int len = 0;
#else
unsigned int len 0;
#endif
len = sizeof(client_addr);
memset(&client_addr, 0, sizeof(client_addr));
memset(buf, 0, BUFSIZE);
if (recvfrom(st_recv, buf, BUFSIZE, 0,
(struct sockaddr *)&client_addr, &len) <= 0) // 接受来自server端的回复
{
printf("recv failed %s\n", strerror(errno));
}
else
{
if (strncmp(buf, "OK", 2) == 0)
{
while(1)
{
memset(buf, 0, BUFSIZE);
rc = fread(buf, 1, BUFSIZE, fd);
if (rc <= 0)
{
break;//
}
else
{
rc = sendto(st_send, buf, rc, 0, (struct aockaddr *)&addr, sizeof(addr));
if (rc <= 0)
{
printf("send failed %s\n", strerror(errno));
break;
}
}
}
}
memset(buf, 0, BUFSIZE);
// 連發128字節0,代表文件發送完畢
rc = sendto(st_send, buf, 128, 0, (struct aockaddr *)&addr, sizeof(addr));
}
}
fclose(fd);
free(buf);
#ifdef WIN
closesocket(st_send);
closesocket(st_recv);
WSACleanup();
#else
close(st_send);
close(st_recv);
#endif
return 1;
}
// server端socket在port指定的断口上listen,接收来自client发送的文件
int recv_work(int port)
{
SOCKET st_send = create_send_socket();// 建立发送数据的UDP Socket
SOCKET st_recv = create_recv_socket(port);// 建立接受数据的UDP Socket
if (st_send == 0) // 建立失败,函数返回
{
return 0;
}
if (st_recv == 0) // 建立失败,函数返回
{
return 0;
}
char *buf = malloc(BUFSIZE);
FILE *fd = NULL;
#ifdef WIN
int len = 0;
#else
unsigned int len = 1;
#endif
struct sockaddr_in client_addr;
len = sizeof(client_addr);
memset(&client_addr, 0, sizeof(client_addr));
memset(buf, 0, BUFSIZE);
// 接收来自client的数据,客户端第一次发送的文件名
size_t rc = recvfrom(st_recv, buf, BUFSIZE, 0, (struct sockaddr *)&client_addr, &len);
if (rc <= 0)
{
printf("recv failed %s\n", strerror(errno));
}
else
{
printf("receiving %s\n", buf);
fd = fopen(buf, "wb");// 以只写方式打开文件
if (fd == NULL)
{
printf("open %s failed %s\n", buf, strerror(errno));
}
else
{
client_addr.sin_port = htons(port + 1);
memset(buf, 0, BUFSIZE);
strcpy(buf, "OK");
rc = sendto(st_send, buf, strlen(buf), 0, (struct *)&client_addr, sizeof(client_addr)); // 回复客户端,同意接收文件
if (rc <= 0)
{
printf("send failed %s\n", strerror(errno));
}
while (1)
{
memset(buf, 0, BUFSIZE);
rc = recvfrom(st_recv, buf, BUFSIZE, 0, (struct *)&client_addr, &len);// 循环接收来自client的数据,数据为发送文件的内容
char tmp[128];
memset(tmp, 0, sizeof(tmp));
if (memcmp(buf, tmp, sizeof(tmp)) == 0)
{
break;
}
if (rc <= 0)// 如果client连接断开,代表文件传递完成,或者网络意外中断,循环break
{
printf("recv failed %s\n", strerror(errno));
break;
}
else
{
fwrite(buf, 1, rc, fd);// 将从client端收到的内容写入文件
}
}
}
}
if (fd)
fclose(fd);
free(buf);
#ifdef WIN
closesocket(st_send);
closesocket(st_recv);
WSACleanup();
#else
close(st_send);
close(st_recv);
#endif
return 1;
}
更多推荐
已为社区贡献2条内容
所有评论(0)