UNPv13:#第5章#TCP客户/服务器程序示例
2017-12-19 17:16
281 查看
Code
github//server.c #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <signal.h> #include <wait.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> void sig_chld(int signo) { pid_t pid; int stat; while((pid = waitpid(-1, &stat, WNOHANG)) > 0) printf("child %d terminated\n", pid); return; } int main(int argc, char* argv[]) { int listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(listenfd == -1) { perror("function socket error :"); exit(-1); } struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(atoi(argv[1])); if(bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) { perror("function bind error : "); exit(-1); } if(listen(listenfd, 5) == -1) { perror("function listen error : "); exit(-1); } struct sigaction act, oact; act.sa_handler = sig_chld; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGCHLD, &act, &oact) == -1) { perror("function sigaction error : "); exit(-1); } int connfd; struct sockaddr_in clientaddr; socklen_t clientlen; while(1) { clientlen = sizeof(clientaddr); connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientlen); if(connfd == -1) { if(errno == EINTR) continue; perror("function accept error : "); exit(-1); } if(fork() == 0) { if(close(listenfd) == -1) { perror("function close error : "); exit(-1); } char buf[1024]; int len; AGAIN: while((len = read(connfd, buf, 1024)) > 0) write(connfd, buf, len); if(len < 0 && errno == EINTR) goto AGAIN; else if(len < 0) { perror("function read error : "); exit(1); } } else { if(close(connfd) == -1) { perror("function close error : "); exit(-1); } } } return 0; }
//client.c #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char* argv[]) { int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sockfd == -1) { perror("function socket error : "); exit(-1); } struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; switch(inet_pton(AF_INET, argv[1], &serveraddr.sin_addr)) { case 0: perror("function inet_pton error (input invalid) : "); exit(-1); break; case 1: //successed break; default: perror("function inet_pton error : "); exit(-1); break; } serveraddr.sin_port = htons(atoi(argv[2])); connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); char buf[1024]; while(fgets(buf, 1024, stdin) != NULL) { write(sockfd, buf, strlen(buf)); if(read(sockfd, buf, 1024) == 0) { perror("server terminated"); exit(0); } fputs(buf, stdout); } return 0; }
服务器进程终止
客户TCP收到FIN只是表示服务器进程已关闭连接的服务端,从而不再往其中发送任何数据而已。FIN的接收并没有告知客户TCP服务器进程已经终止。
SIGPIPE信号
当一个进程向某个已收到RST的套接字执行写操作时,内核向该进程发送一个SIGPIPE信号。该信号默认行为是终止进程。不论该进程捕获该信号并从其信号处理函数返回,还是简单的忽略该信号,写操作都将返回EPIPE。 第一次写操作引发RST,第二次写引发SIGPIPE信号。写一个已接收FIN的套接字不成问题,但写一个已接收了RST的套接字则是一个错误。
相关文章推荐
- UNIX网络编程卷1:套接字联网-第5章:TCP客户/服务器程序示例
- UNIX网络编程 第5章 TCP客户/服务器程序示例
- Unix网络编程代码 第5章 TCP客户/服务器程序示例
- TCP 客户/服务器程序示例
- 【UNIX网络编程】TCP客户/服务器程序示例
- UNIX网络编程笔记 第五章 TCP客户/服务器程序示例
- TCP客户/服务器程序示例
- UNP-UNIX网络编程 第五章:TCP客户/服务器程序示例
- UNIX网络编程---TCP客户/服务器程序示例(五)
- UNIX网络编程笔记(4)—TCP客户/服务器程序示例
- TCp客户/服务器程序示例
- 【UNIX网络编程(三)】TCP客户/服务器程序示例
- TCP客户/服务器程序示例
- UNP卷1:第五章(TCP客户/服务器程序示例)
- Linux网络编程(三) TCP客户/服务器程序示例
- UNIX网络编程卷一 笔记 第五章 TCP客户/服务器程序示例
- UNIX网络编程第5章TCP客户服务器程序示例5.2 5.3 5.4 5.5 5.6 5.7
- UNP函数笔记三: TCP客户/服务器程序示例
- UNPV3第五章TCP客户/服务器程序示例
- 5. TCP客户/服务器程序示例