Linux C/C++ TCP Socket传输文件或图片实例
环境:Linux
语言:C/C++
通信方式:TCP
下面用TCP协议编写一个简单的服务器、客户端,其中服务器端一直监听本机的6666号端口。如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建立连接。连接建立成功后,读取文件内容(/root/workspace/socket-picture/bizhi.jpg),发送给服务器端,服务器端新建new1.jpg文件,将接收到的文件内容保存到new1.jpg中,new1.jpg在当前目录下;
Server.cpp
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<errno.h> 5 #include<sys/types.h> 6 #include<sys/socket.h> 7 #include<netinet/in.h> 8 #include<unistd.h> 9 10 #define MAXLINE 4096 11 12 int main(int argc, char** argv){ 13 int listenfd, connfd; 14 struct sockaddr_in servaddr; 15 char buff[4096]; 16 FILE *fp; 17 int n; 18 19 if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ 20 printf("create socket error: %s(errno: %d)\n",strerror(errno),errno); 21 return 0; 22 } 23 printf("----init socket----\n"); 24 25 memset(&servaddr, 0, sizeof(servaddr)); 26 servaddr.sin_family = AF_INET; 27 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 28 servaddr.sin_port = htons(6666); 29 //设置端口可重用 30 int contain; 31 setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &contain, sizeof(int)); 32 33 if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){ 34 printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno); 35 return 0; 36 } 37 printf("----bind sucess----\n"); 38 39 if( listen(listenfd, 10) == -1){ 40 printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno); 41 return 0; 42 } 43 if((fp = fopen("new1.jpg","ab") ) == NULL ) 44 { 45 printf("File.\n"); 46 close(listenfd); 47 exit(1); 48 } 49 50 printf("======waiting for client's request======\n"); 51 while(1){ 52 struct sockaddr_in client_addr; 53 socklen_t size=sizeof(client_addr); 54 if( (connfd = accept(listenfd, (struct sockaddr*)&client_addr, &size)) == -1){ 55 printf("accept socket error: %s(errno: %d)",strerror(errno),errno); 56 continue; 57 } 58 while(1){ 59 n = read(connfd, buff, MAXLINE); 60 if(n == 0) 61 break; 62 fwrite(buff, 1, n, fp); 63 } 64 buff[n] = '\0'; 65 printf("recv msg from client: %s\n", buff); 66 close(connfd); 67 fclose(fp); 68 } 69 close(listenfd); 70 return 0; 71 }
Client.cpp
1 #include <stdio.h> 2 #include <errno.h> 3 #include <string.h> 4 #include <netdb.h> 5 #include <sys/types.h> 6 #include <netinet/in.h> 7 #include <sys/socket.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 #include <arpa/inet.h> 11 #include <netdb.h> 12 #define MAXLINE 4096 13 14 int main(int argc, char** argv){ 15 int sockfd, len; 16 char buffer[MAXLINE]; 17 struct sockaddr_in servaddr; 18 FILE *fq; 19 20 if( argc != 2){ 21 printf("usage: ./client <ipaddress>\n"); 22 return 0; 23 } 24 25 if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 26 printf("create socket error: %s(errno: %d)\n", strerror(errno),errno); 27 return 0; 28 } 29 30 memset(&servaddr, 0, sizeof(servaddr)); 31 servaddr.sin_family = AF_INET; 32 servaddr.sin_port = htons(6666); 33 if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){ 34 printf("inet_pton error for %s\n",argv[1]); 35 return 0; 36 } 37 38 if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ 39 printf("connect error: %s(errno: %d)\n",strerror(errno),errno); 40 return 0; 41 } 42 if( ( fq = fopen("/root/workspace/socket-picture/bizhi.jpg","rb") ) == NULL ){ 43 printf("File open.\n"); 44 close(sockfd); 45 exit(1); 46 } 47 48 bzero(buffer,sizeof(buffer)); 49 while(!feof(fq)){ 50 len = fread(buffer, 1, sizeof(buffer), fq); 51 if(len != write(sockfd, buffer, len)){ 52 printf("write.\n"); 53 break; 54 } 55 } 56 close(sockfd); 57 fclose(fq); 58 59 return 0; 60 }
makefile
1 all:server client 2 server:server.o 3 g++ -g -o server server.o 4 client:client.o 5 g++ -g -o client client.o 6 server.o:server.cpp 7 g++ -g -c server.cpp 8 client.o:client.cpp 9 g++ -g -c client.cpp 10 clean:all 11 rm all
执行make命令后,生成server和client两个可执行文件。分别打开两个终端窗口,一个执行./server命令,一个执行./client 127.0.0.1命令,表示连上本机的6666端口,执行./server命令的要先执行。执行./client 127.0.0.1命令后,client客户端执行完毕直接退出,这时可以看到server的那个终端窗口输出“recv msg from client:”。打开当前目录(指的是可执行文件server所在的目录),可看到new1.jpg文件已经生成,双击打开,文件内容没有丢失。