linux网络编程之实现跨平台PC之间进行文件传输

来源:互联网 发布:dsm数据 编辑:程序博客网 时间:2024/06/06 19:21

//实现两台计算机进行文件传输,包括跨平台传输即linux与windows之间
//TCP的文件传输
//文件大小不限制,需要做到将大文件分包去做

server.c

//服务端程序int main(int arg,char * args[ ]){if(arg < 2){printf("scanf parameter failed\n");return 0;}int port = itoi(args[1]);if(port == 0){printf("port %d is invalid\n ",port);return 0;}printf("receive begin\n");if(recv_work(port) == 1)printf("receive success\n");elseprintf("receive failed\n");return 0;}

client.c

//实现两台计算机进行文件传输,包括跨平台传输即linux与windows之间//TCP的文件传输//文件大小不限制,需要做到将大文件分包去做//编译时传入的参数是包括:服务器IP地址、端口号、传送的文件名//client端int main(int arg,char * args[ ]){//先是判断传入的参数个数if(arg < 4){printf("scanf parameter failed\n");return 0;}//判断端口号int port = atoi(args[2]);if(port == 0){printf("port %d is invalid\n ",port);return 0;}printf("%s send begin\n",args[3]);//将调用一个send_work函数传入服务器IP地址、端口号、传送的文件名if(send_work(args[1],port,args[3]) == 1){sleep(3);printf("%s send success\n",args[3]);}else{printf("%s send failed\n",args[3]);}return EXIT_SUCCESS;}

pub.h

#ifndef PUB_H_#define PUB_H_int send_work(const char * hostname,int port,const char * filename);int recv_work(int port);#endif /* PUB_H_ */

pub.c

#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//为什么要定义一个宏,解释一下,因为此程序可以保证在linux与windows系统下均可运行。//#ifdef WIN//#include <WinSock2.h>//#else 为什么这样写呢,在windows下socket被封装在此头文件下,而且套接口的类型为SOCKET,而linux下的套接口为int型,故作此标记int init_socket(){//如果是windows系统,执行如下代码,linux系统直接略过此代码#ifdef WINWORD 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;}#endifreturn 0;}SOCKET socket_connect(const char * hostname,int port)//连接IP地址和port端口号{if(init_socket() == -1)//因为linux与windows系统下使用socket有区别,windows下必须使用此函数初始化(同样用到宏)return 0;SOCKET st = socket(AF_INET,SOCK_STREAM,0);if(st == 0)return 0;struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(hostname);if(connect(st,(struct sockaddr *) &addr,sizeof(addr)) == -1){printf("connect to %s:%d failed %s\n", hostname, port, strerror(errno));return 0; // 连接失败,返回0}else{return st;}}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]);}//连接到hostname指定的IP地址和port端口号int send_work(const char * hostname,int port,const char * filename){SOCKET st = socket_connect(hostname,port);if(st == 0)return 0;//连接成功后,需要将传送的文件打开FILE * fd = fopen(filename,"rb");if(fd == NULL)//判断文件描述符,看文件是否打开{printf("open %s failed\n",filename);return 0;}char *buf = malloc(BUFSIZE) ;//申请一个缓冲区,将文件数据放置在此memset(buf,0,BUFSIZE);//将完整的文件名解析出来getfilename(filename,buf);//将解析出来的文件名先发送给服务端,等待服务端接收,若接收成功并返回一个信号给客户端int rc = send(st,buf,strlen(buf),0);if(rc <= 0)//在判断一下是否成功发出{if(rc < 0)printf("send failed %s\n", strerror(errno));elseprintf("socket disconnect\n");}else{memset(buf,0,sizeof(buf));//等待服务器端传来的消息if(recv(st,buf,BUFSIZE,0) <= 0){printf("socket disconnect\n");}else{if(strncmp(buf,"OK",2) == 0){while(1){memset(buf,0,BUFSIZE);rc = fread(buf,1,BUFSIZE,fd);if(rc <= 0){if (rc < 0)   printf("fread failed %s\n", strerror(errno));break;}else{rc = send(st,buf,rc,0);if(rc <= 0){if (rc < 0) printf("fread failed %s\n", strerror(errno));elseprintf("socket disconnect\n");break;}printf("我已发送\n");}}}}}fclose(fd);free(buf);#ifdef WINclosesocket(st);WSACleanup();#elseclose(st);#endifreturn 1;}SOCKET socket_create(int port){SOCKET st = socket(AF_INET,SOCK_STREAM,0);//初始化socketif(st == 0)return 0;#ifdef WINconst char on = 0;#elseint on = 0;#endifif (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){printf("setsockopt failed %s\n", strerror(errno));return EXIT_FAILURE;}struct sockaddr_in addr;//定义一个IP地址的结构memset(&addr,0,sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(8080);addr.sin_addr.s_addr = htonl(INADDR_ANY);//服务器端程序,需要使用bind将IP与server程序绑定if(bind(st,(struct sockaddr *) &addr,sizeof(addr)) == -1){printf("bind failed %s\n", strerror(errno));return 0;}if(listen(st,20) == -1){printf("listen failed %s\n", strerror(errno));return 0;}printf("listen success\n");return st;}// server端socket开始accept的函数SOCKET socket_accept(SOCKET client_st){struct sockaddr_in client_addr;memset(&client_addr,0,sizeof(client_addr));#ifdef WIN    int len = 0;#else    unsigned int len = 1;#endif    len = sizeof(client_addr);    SOCKET listen_st = accept(client_st,(struct sockaddr *) &client_addr,&len);//阻塞调用    if (listen_st == -1)    {    printf("accept failed %s\n", strerror(errno));    return EXIT_FAILURE;    }    else    {    printf("accept by %s\n",inet_ntoa(client_addr.sin_addr));    return listen_st;    }}// server端socket在port指定的断口上listen,接收来自client发送的文件int recv_work(int port){SOCKET st = socket_create(port);// 建立server端socket,在port指定的端口listenif(st == 0)return 0;// 如果有client连接到,socket_accept函数返回client的socketSOCKET listen_st = socket_accept(st);if(listen_st == 0)return 0;char *buf = malloc(BUFSIZE);memset(buf,0,BUFSIZE);FILE * fd = NULL;size_t rc = recv(listen_st,buf,BUFSIZE,0);//接收来自client的数据,客户端第一次要发送的文件名称if(rc <= 0){if(rc < 0)printf("receive failed %s\n", strerror(errno));elseprintf("socket disconnect\n");}else{printf("receicing %s\n",buf);fd = fopen(buf,"wb");//以只写的方式打开if(fd == NULL){printf("open %s failed %s\n", buf, strerror(errno));return 0;}else{memset(buf,0,BUFSIZE);strcpy(buf,"OK");rc = send(listen_st,buf,strlen(buf),0);if(rc <= 0){if(rc < 0)printf("send failed %s\n", strerror(errno));elseprintf("socket disconnect\n");}while(1){memset(buf,0,BUFSIZE);rc = recv(listen_st,buf, BUFSIZE, 0);if(rc <= 0)// 如果client连接断开,代表文件传递完成,或者网络意外中断,循环break{if(rc < 0)printf("receive failed %s\n", strerror(errno));elseprintf("socket disconnect\n");break;}else{fwrite(buf,1,rc,fd);// 将从client端收到的内容写入文件}}}}if(fd)fclose(fd);free(buf);#ifdef WIN    closesocket(st);    closesocket(listen_st);    WSACleanup();#else    close(st);    close(listen_st);#endifreturn 1;}

在windows下的makfile代码:

.SUFFIXES:.c .o    CC=gcc  SERVERSRCS=file_server.c\  pub.c  CLIENTSRCS=file_socket.c\  pub.c  SERVEROBJS=$(SERVERSRCS:.c=.o)  CLIENTOBJS=$(CLIENTSRCS:.c=.o)  SERVEREXEC=server.exe  CLIENTEXEC=client.exe  all: $(SERVEROBJS) $(CLIENTOBJS)  $(CC) -static -o $(SERVEREXEC) $(SERVEROBJS)  $(CC) -static  -o $(CLIENTEXEC) $(CLIENTOBJS)  @echo '----------------ok----------------'    .c.o:  $(CC) -Wall -DWIN  -g -o $@ -c $<    clean:  rm -f $(SERVEROBJS)  rm -f $(CLIENTOBJS)  rm -f core* 

linux下的makefile文件:

.SUFFIXES:.c .o    CC=gcc  SERVERSRCS=file_server.c\  pub.c  CLIENTSRCS=file_socket.c\  pub.c  SERVEROBJS=$(SERVERSRCS:.c=.o)  CLIENTOBJS=$(CLIENTSRCS:.c=.o)  SERVEREXEC=server  CLIENTEXEC=client    all: $(SERVEROBJS) $(CLIENTOBJS)  $(CC) -o $(SERVEREXEC) $(SERVEROBJS)  $(CC) -o $(CLIENTEXEC) $(CLIENTOBJS)  @echo '----------------ok----------------'    .c.o:  $(CC) -Wall -g -o $@ -c $<    clean:  rm -f $(SERVEROBJS)  rm -f $(CLIENTOBJS)  rm -f core* 


0 0
原创粉丝点击