下面是socket編程的服務器端編程
先看一個圖,1數組
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> //針對系統調用的封裝 fork,pipe 各類i/o原語 read write 等 5 6 #include<sys/socket.h> 7 #include<netinet/in.h> //互聯網地址族 定義數據結構sockaddr_in 8 #include<arpa/inet.h> //提供IP地址轉換函數 9 10 #include<ctype.h> //一批C語言字符分類函數 用 於 測試字符是否屬於特定的字符類別 topper()在這裏 11 12 #define MAXLINE 80 13 #define SER_PORT 8000 14 15 int main(void){ 16 17 struct sockaddr_in servaddr,cliaddr; 18 socklen_t cliaddr_len; 19 20 int listenfd,connfd; 21 char buf[MAXLINE]; 22 char str[INET_ADDRSTRLEN]; 23 int i,n; 24 char tt[] = "exit1"; //這裏有字符數組和字符指針的區別的坑 具體百度查詢 25 char *bb; 26 27 listenfd = socket(AF_INET,SOCK_STREAM,0); // 28 // domain 協議域 AF_INET AF_INET6,AF_LOCAL(AF_UNIX) AF_ROUTE 29 // type socket類型 SOCK_STREAM(流式socket 針對tcp ) SOCK_DGRAM(數據包 針對udp) SOCK_RAW 30 // protocol 協議 tcp協議,udp協議 stcp協議 tipc協議 31 32 bzero(&servaddr,sizeof(servaddr)); //初始化賦值爲0 33 34 servaddr.sin_family = AF_INET; 35 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //任何ip //這裏是大小端的 轉換問題。。能夠 百度 36 servaddr.sin_port = htons(SER_PORT); //端口 37 38 bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); //綁定連接的套接字描述符 和 地址和端口 39 40 listen(listenfd,20); 41 42 printf("Accepting connections ... \n "); 43 while(1){ 44 45 cliaddr_len = sizeof(cliaddr); 46 connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); //鏈接的套接字描述符 返回連接的地址 返回地址的緩衝區長度 47 48 //返回 客戶端的套接字描述符 49 printf("connfd:%d------\n",connfd); 50 51 printf("received from %s at PORT %d \n", 52 inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)), 53 ntohs(cliaddr.sin_port)); 54 while(1){ 55 n = read(connfd,buf,MAXLINE); // read(int fd,void *buf, size_t count); 成功返回 讀取的字節數 數據保存在buf上 讀取客戶端的數據 56 57 printf("%d,") 58 //printf("buf:%s-----%d\n",buf,strcmp(buf,"exit1")); 59 //printf("tt:%s-----%d\n",tt,strcmp(tt,"exit1")); 60 for(int i=0;i<5;i++){ 61 tt[i] = buf[i]; 62 } 63 printf("tt:%s-----%d\n",tt,strcmp(tt,"exit1")); 64 if(strcmp(tt,"exit1") == 0){ //strcmp 對比的就是字符 65 close(connfd); 66 printf("close:-----\n"); 67 break; 68 } 69 70 for(i=0; i < n; i++){ 71 buf[i] = toupper(buf[i]); 72 } 73 write(connfd,buf,n); // // 向客戶端寫入數據 74 } 75 76 } 77 78 return 0; 79 80 } 81 82 //這個程序有漏洞,若是客戶端斷線或者關閉,服務器就會死循環。 客戶端的標準輸入是阻塞的。。。其餘都不是阻塞的。
客戶端服務器
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 6 #include<sys/socket.h> 7 #include<netinet/in.h> 8 #include<arpa/inet.h> 9 10 #include<errno.h> //錯誤 11 12 #define MAXLINE 80 13 #define SER_PORT 8000 14 15 int main(int argc,char *argv[]){ 16 17 18 struct sockaddr_in servaddr; 19 char buf[MAXLINE]; 20 21 int sockfd,n; 22 char *str; 23 char tt[5]; 24 25 //if(argc != 2){ 26 // fputs("usage: ./client message \n ",stderr); 27 // exit(1); 28 //} 29 30 //str = argv[1]; 31 32 sockfd = socket(AF_INET,SOCK_STREAM,0); 33 34 bzero(&servaddr,sizeof(servaddr)); 35 servaddr.sin_family = AF_INET; 36 inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr); 37 servaddr.sin_port = htons(SER_PORT); 38 39 if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0){ 40 printf("connet error:%s\n",strerror(errno)); 41 } //連接服務器 42 43 while(1){ 44 45 memset(buf,0,MAXLINE); 46 printf("client connet server ...\n"); 47 n = read(STDIN_FILENO,buf,MAXLINE); //從標準輸入 讀取數據 48 for(int i=0;i<5;i++){ 49 tt[i] = buf[i]; 50 } 51 if(strcmp(tt,"exit1") == 0){ 52 printf("exit server connect \n"); 53 close(sockfd); 54 return 0; 55 } 56 57 write(sockfd,buf,n); //把咱們的輸入,寫到服務器 58 59 if(strcmp(tt,"exit1") == 0){ 60 printf("exit server connect \n"); 61 close(sockfd); 62 return 0; 63 } 64 65 n = read(sockfd,buf,MAXLINE); //從服務器讀取數據 66 67 68 printf("Response from server:\n"); 69 write(STDOUT_FILENO,buf,n); //寫到標註輸出上 70 printf("\n"); 71 } 72 73 close(sockfd); 74 return 0; 75 76 }
實驗結果:數據結構
總結:一個socket創建一個鏈接,必須配合一個connect,對應的服務器端對應一個accept 。不能屢次connet,屢次是以後會報錯,也不能同一個客戶端socket屢次accept,由於服務器已經有了,accept會阻塞等待其餘客戶端的socket。dom