tcp

xiaoxiao2021-02-27  186

//server.c //version1server和clien #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/socket.h> #include<sys/types.h> #include<arpa/inet.h> #include<netinet/in.h> void Usage(char* proc) { printf("Uasge:%s[local_ip][local_port]\n",proc); exit(2); } int startup(char* ip,int port) { int sock=socket(AF_INET,SOCK_STREAM,0); if(sock<0) { perror("socket\n"); exit(3); } struct sockaddr_in server; server.sin_family=AF_INET; server.sin_port=htons(port); server.sin_addr.s_addr=inet_addr(ip); if(bind(sock,(struct sockaddr*)&server,sizeof(server))<0) { perror("bind\n"); exit(4); } if(listen(sock,10)<0) { perror("listen\n"); exit(5); } return sock; } int main(int argc,char* argv[]) { if(argc!=3) { Usage(argv[0]); exit(1); } int listen_sock=startup(argv[1],atoi(argv[2])); printf("fd:%d\n",listen_sock); while(1) { struct sockaddr_in client; socklen_t len=sizeof(client); int newsock=accept(listen_sock,(struct sockaddr*)&client,&len); if(newsock<0) { perror("accept\n"); continue; } printf("get a new client :%s %d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); char buf[1024]; while(1) { ssize_t s=read(newsock,buf,sizeof(buf)-1); if(s<0) { perror("read\n"); exit(6); } if(s==0) { printf("client quit\n"); exit(7); } else { buf[s]=0; printf("client say:%s\n",buf); write(newsock,buf,sizeof(buf)-1) ; } } close(newsock); } close(listen_sock); return 0; } //多进程版本 #include<stdio.h> #include <sys/types.h> #include <sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> #include<string.h> #include<unistd.h> #include<stdlib.h> int startup(char*ip, int port) { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock<0) { perror("socket"); exit(2); } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = inet_addr(ip); if (bind(sock, (struct sockaddr*)&server, sizeof(struct sockaddr_in))<0) { perror("bind"); exit(3); } if (listen(sock, 10)<0) { perror("listen"); exit(4); } return sock; } void usage(const char*proc) { printf("%s [local_ip] [local_port]\n", proc); exit(5); } int main(int argc, char* argv[]) { if(argc!=3) { usage(argv[0]); } int listen_sock = startup(argv[1], atoi(argv[2])); printf("fd:%d\n", listen_sock); while (1) { struct sockaddr_in client; socklen_t len = sizeof(client); int newsock = accept(listen_sock, (struct sockaddr*)&client, &len); if (newsock<0) { perror("accept"); continue; } printf("get a client:[%s:%d]\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); pid_t id = fork(); if (id == 0) { close(listen_sock); if (fork() == 0) { char buf[1024]; while (1) { ssize_t ret = read(newsock, buf, sizeof(buf)-1); if (ret>0) { buf[ret] = 0; printf("client say:%s\n", buf); write(newsock, buf, sizeof(buf)-1); } else if (ret == 0) { printf("client quit!\n"); close(newsock); exit(7); } else { perror("read"); exit(8); } } } else { exit(9); } } else if (id>0) { close(newsock); while((waitpid(-1,NULL,WNOHANG)>0)); continue; } else { perror("fork"); exit(9); } } close(listen_sock); return 0; } //多线程版本 #include<stdio.h> #include <sys/types.h>          #include <sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> #include<string.h> #include<unistd.h> #include<stdlib.h> #include <pthread.h> void usage(char* proc) {    printf("usage:%s [local_ip][local_port]\n",proc);     exit(2); } int startup(char* ip,int port) {     int sock=socket(AF_INET,SOCK_STREAM,0);     if(sock<0)     {         perror("socket\n");         exit(3);     }     struct sockaddr_in server;     server.sin_family=AF_INET;     server.sin_port=htons(port);     server.sin_addr.s_addr=inet_addr(ip);     if(bind(sock,(struct sockaddr*)&server,sizeof(server))<0)     {         perror("bind\n");         exit(4);     }     if(listen(sock,10)<0)     {         perror("listen\n");         exit(5);     }     return sock; } void* thread_handler(void* arg) {     int newsock=*((int*)arg);     char buf[1024];     while(1)     {         ssize_t ret=read(newsock,buf,sizeof(buf)-1);         if(ret<0)         {             perror("read\n");             exit(8);         }        else if(ret==0)         {             printf("client quit\n");            exit(9);             }         else{             buf[ret]=0;             printf("client say:%s\n",buf);             write(newsock,buf,sizeof(buf)-1);                     }     } } int main(int argc,char* argv[]) {     if(argc!=3)     {         usage(argv[0]);         exit(1);     }     int listen_sock=startup(argv[1],atoi(argv[2]));     printf("fd:%d\n",listen_sock);   while(1)     {         struct sockaddr_in client;         socklen_t len=sizeof(client);         int newsock=accept(listen_sock,(struct sockaddr*)&client,&len);         if(newsock<0)         {             perror("accept\n");              exit(6);         }         printf("get a new client:[%s:%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));         pthread_t tid;         int ret=pthread_create(&tid,NULL,thread_handler,&newsock);         if(ret<0)         {             perror("pthread_create\n");             exit(7);         } pthread_detach(tid);      }     close(listen_sock); return 0; } //client #include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<arpa/inet.h> #include<netinet/in.h> #include<string.h> #include<unistd.h> #include<stdlib.h> void Usage(char* proc) { printf("Usage:%s[local_ip][local_port]\n",proc); exit(2); } int main(int argc,char* argv[]) { if(argc!=3) { Usage(argv[0]); exit(1);} int sock=socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in server_sock; server_sock.sin_family=AF_INET; server_sock.sin_port=htons(atoi(argv[2])); server_sock.sin_addr.s_addr=inet_addr(argv[1]); if(connect(sock,(struct sockaddr*)&server_sock,sizeof(server_sock))<0) { perror("connect\n"); exit(3); } while(1) { printf("please enter:"); fflush(stdout); char buf[1024]; ssize_t ret=read(0,buf,sizeof(buf)-1); if(ret>0) { buf[ret-1]=0; write(sock,buf,sizeof(buf)-1); read(sock,buf,sizeof(buf)-1); printf("server say:%s\n",buf); } } close(sock); return 0; }

 server bind 失败的原因及解决方法?

client终⽌时⾃动关闭socket描述符,server的TCP连接收到client发的FIN段后处于TIME_WAIT状 态。TCP协议规定,主动关闭连接的一⽅要处于TIME_WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态,因为我们先Ctrl-C终⽌了server,所以server是主动关闭连接的⼀⽅,在TIME_WAIT期间仍然不能再次监听同样的server端 ⼜口。MSL在RFC1122中规定为两分钟,但是各操作系统的实现不同,在Linux上一般经过半分钟后 就可以再次启动server了。解决这个问题的⽅法是使用setsockopt()设置socket描述符的 选项SO_REUSEADDR为1,表示允许创建端⼜口号相同但IP地址不同的多个socket描述符。即将其设置为非阻塞就可以。

转载请注明原文地址: https://www.6miu.com/read-9700.html

最新回复(0)