Socket编程实践(6)

僵尸进程处理

1)通过忽略SIGCHLD信号,避免僵尸进程

在server端代码中添加

signal(SIGCHLD,SIG_IGN);

2)通过wait/waitpid方法,解决僵尸进程

signal(SIGCHLD,onSignalCatch);void onSignalCatch(int signalNumber){wait(NULL);}

3)如果多个客户端同时关闭,问题描述如下面两幅图所示:

/** client端实现的测试代码**/int main(){int sockfd[50];for (int i = 0; i < 50; ++i){if ((sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) == -1)err_exit("socket error");struct sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8001);serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");if (connect(sockfd[i], (const struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)err_exit("connect error");}sleep(20);}

在客户运行过程中按下Ctrl+C,则可以看到在server端启动50个子进程,并且所有的客户端全部一起断开的情况下,产生的僵尸进程数是惊人的(此时也证明了SIGCHLD信号是不可靠的)!

解决方法-将server端信号捕捉函数改造如下:

void sigHandler(int signo){while (waitpid(-1, NULL, WNOHANG) > 0);}

且没有结束的迹象,返回0).Onerror,-1isreturned.

地址查询API#include <sys/socket.h>int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//获取本地addr结构int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//获取对方addr结构int gethostname(char *name, size_t len);int sethostname(const char *name, size_t len);#include <netdb.h>extern int h_errno;struct hostent *gethostbyname(const char *name);#include <sys/socket.h>/* for AF_INET */struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);struct hostent *gethostent(void);//hostent结构体struct hostent{char *h_name;/* official name of host */char **h_aliases;/* alias list */int h_addrtype;/* host address type */int h_length;/* length of address */char **h_addr_list;/* list of addresses */}#define h_addr h_addr_list[0] /* for backward compatibility *//**获取本机IP列表**/int gethostip(char *ip){struct hostent *hp = gethostent();if (hp == NULL)return -1;strcpy(ip, inet_ntoa(*(struct in_addr*)hp->h_addr));return 0;}int main(){char host[128] = {0};if (gethostname(host, sizeof(host)) == -1)err_exit("gethostname error");cout << "host-name: " << host << endl;struct hostent *hp = gethostbyname(host);if (hp == NULL)err_exit("gethostbyname error");cout << "ip list: " << endl;for (int i = 0; hp->h_addr_list[i] != NULL; ++i){cout << ‘\t'<< inet_ntoa(*(struct in_addr*)hp->h_addr_list[i]) << endl;}char ip[33] = {0};gethostip(ip);cout << "local-ip: " << ip << endl;}TCP协议的11种状态

1.如下图(客户端与服务器都在本机:双方(server的子进程,与client)链接已经建立(ESTABLISHED),等待通信)

2.最先close的一端,会进入TIME_WAIT状态;而被动关闭的一端可以进入CLOSE_WAIT状态(下图,server端首先关闭)

3.TIME_WAIT时间是2MSL(报文的最长存活周期的2倍)

  原因:(ACKy+1)如果发送失败可以重发,因此如果server端不设置地址重复利用的话,服务器在短时间内就无法重启;

服务器端处于closed状态,不等于客户端也处于closed状态。

(下图,client先close,client出现TIME_WAIT状态)

当你能梦的时候就不要放弃梦

Socket编程实践(6)

相关文章:

你感兴趣的文章:

标签云: