TCP文件传输

来源:互联网 发布:动态导入java 编辑:程序博客网 时间:2024/05/22 07:46

下面是一个简单的TCP文件传输的例子,实现环境:Linux C

Server.c

// 向客户端发送文件#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#define MAXBUFF 1024// 通过sock来发送指定的文件int sendFile(char *srcFile, int sock){int inFile;if((inFile = open(srcFile, O_RDONLY)) == -1) //只读方式打开test.txt ,iffile文件指针{printf("找不到文件[%s]或打不开, 停止运行\n", srcFile);return -1;// 发送文件失败}int nread;char buf[MAXBUFF] = {0};while((nread = read(inFile, buf, MAXBUFF)) > 0){if(write(sock, buf, nread) == -1)// 将缓冲区的内容写到sockprintf("写sock出了错\n");}close(inFile);return 0;// 发送文件成功}int main(){int sock,length,clilen;struct sockaddr_in server, client;/******************************建立Socket连接*********************************/sock = socket(AF_INET,SOCK_STREAM,0); //申请socket资源if (sock < 0){perror("socket");return 1;}server.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;// 必然的,这里指的是Internet协议*/server.sin_port = 0;// 这里,是让系统自动分配一个端口号,在1024到5000之间65535个端口 ,端口设为0,系统自动分配  if (bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) // 将IP地址和端口号绑到sock上{perror("bind");return 1;}length = sizeof(server);if (getsockname(sock, (struct sockaddr *)&server, &length) < 0) /*获得指定socket的本地地址,成功返回0,错误返回-1*/{perror("getsockname");return 1;}printf("Socket port #%d\n", ntohs(server.sin_port)); /* 打印出系统分的端口号,给client用*/listen(sock, 5);/*5个连接请求排队等待,一般5个 Pause Here 等待client连接*//****************现在是等待客户来连接,如果来客户了,那就建好了socket,就可以当文件使用**********/clilen = sizeof(client);   int msgsock = accept(sock,(struct sockaddr *)&client,(int *) &clilen);/*创建一个新的与sock相同的socket并返回其值*/if (msgsock == -1)perror("accept");else{char srcFile[] = "test.txt";if(sendFile(srcFile, msgsock) == 0)printf("发送文件[%s]成功\n", srcFile);elseprintf("发送文件[%s]失败\n", srcFile);} close(msgsock);// 关闭临时套接字close(sock);return 0;}


Client.c

// 功能:接收服务器发送过来的数据,保存到本地文件#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#define MAXBUFF 1024#define PERM 0644// 创建文件的默认属性// 通过sock接收数据保存到文件destFileint recvFile(char *destFile, int sock){int outFile, nread;char buf[MAXBUFF] = {0};if((outFile = open(destFile, O_WRONLY|O_CREAT|O_TRUNC, PERM)) == -1) //创建文件return 1;while((nread = read(sock, buf, MAXBUFF)) > 0) /*从sock读取传来的文件内容到缓冲区*/{ if(write(outFile, buf, nread) == -1)/*将缓冲区的内容写到文件里*/{printf("写文件时出错, 中止接收文件\n");close(outFile);return 1;}}close(outFile);return 0;}int main(int argc, char *argv[]){int sock;struct sockaddr_in server;struct hostent *hp;if(argc < 3){printf("Usage: %s <hostname> <server port>\n", argv[0]);return 1;}sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){perror("socket");return 1;}server.sin_family = AF_INET;hp = gethostbyname(argv[1]); /*根据主机名查地址,返回指针指向hostent结构*/if (hp == 0){fprintf(stderr, "%s: unknown host\n", argv[1]);return 1;}memcpy((char *)&server.sin_addr,(char *)hp->h_addr, hp->h_length);// 拷贝Internet地址server.sin_port = htons(atoi(argv[2]));// argv[2]是服务器端口号if (connect(sock,(struct sockaddr *)&server,sizeof(server)) < 0)// 根据server地址连接sock,建立一条真实的连接{perror("connect");close(sock);return 1;}char destFile[] = "test_out.txt";if(recvFile(destFile, sock) == 0){printf("接收文件[%s]成功\n\n", destFile);}else{printf("创建输出文件[%s]出错, 请检查\n", destFile);}close(sock);return 0;}


如果要检查文件传输过程有没有出错,可以通过命令:wc或计算MD5值来作比较。

我的检测结果:

[zcm@t #64]$cat test.txt |wc     89     183    2901[zcm@t #65]$cat test_out.txt |wc     89     183    2901[zcm@t #66]$md5sum test.txt test_out.txt fffb6bcab6154aad9f7dfe4f5d945bc3  test.txtfffb6bcab6154aad9f7dfe4f5d945bc3  test_out.txt


 

原创粉丝点击