下面是一个简单的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) // 将缓冲区的内容写到sock printf("写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); else printf("发送文件[%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接收数据保存到文件destFile int 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.txt fffb6bcab6154aad9f7dfe4f5d945bc3 test_out.txt