環境: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文件已經生成,雙擊打開,文件內容沒有丟失。