标签:全双工 服务 splay 知识 color unix shu odi perror
任何TCP的实现都需要为MSL选择一个合适的值, RFC的建议值是2分钟。分组可能出现迷途,若迷途分组在MSL中找到路, 造成重复,TCP必须修复
TIME_WAIT
存在的理由:
可靠的实现全双工的连接和终止
考虑最终ACK
丢失的情况,
允许老的重复分组在网络中消逝
TCP的化生身现象, 因为TIME_WAIT
的时间是2MSL, 故TIME_WAIT
可以确保先前化身(incarnation)的老重复分组都已经在网络中消失了
不过存在一个例外: 如果到达的SYN的序列号大于前一化身的结束序列号,源自Berkely的实现应该给当前
TIME_WAIT
状态的连接启动新的化身
连接: 类似TCP, 但是是四路握手, 主要差别在于作为SCTP整体的一部分的cookie的生成
终止: 不允许"半关闭"
inet_pton
and inet_ntop
?inet_addr已经被废弃了, inet_aton其实也不太好, 新的代码应该要使用inet_pton
and inet_ntop
, 例如如下例子
struct sockaddr_in makeAddr(char const *addr, uint16_t port) {
struct sockaddr_in ret{};
inet_pton(AF_INET, addr, &ret.sin_addr.s_addr);
// ret.sin_addr.s_addr = inet_addr(addr); 例如用上面哪行代码代替此行
ret.sin_family = AF_INET;
ret.sin_port = htons(port);
bzero(&ret.sin_zero, 8);
return ret;
}
listen
的作用
??刚由socket
创建的套接字, 系统默认其为主动套接字, listen
的作用是把一个未连接的主动套接字转换为被动套接字. 第二个参数是内核为相应的socket排队的最大排队数 (incomplete connection queue: 处于SYN_RCVD
状态)
void detail() {
pid_t pid;
int listenfd, connfd;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr = makeAddr();
bind(listenfd, (sockaddr *)addr, sizeof(struct sockaddr_in));
listen(listenfd, 128);
while(true) {
struct sockaddr_in clientAddr;
socklen_t addrlen = sizeof(struct sockaddr);
connfd = accept(listenfd, (sockaddr_in) &clientAddr, &addrlen);
if(pid = fork()) {
close(listenfd);
// do something here
close(connfd);
exit(0);
}
close(connfd); //注意这里
}
}
我们知道, TCP套接口字调用close会导致发送一个FIN, 然后会连接终止, 为什么这里不会呢?
??事实上, 每个文件或socket都会有一个引用计数(引用计数在文件表项中维护), fork的时候会让计数*2, 而close让计数-1, 所以不会出现问题, 真正socket的清理和资源的释放过程要等计数为0的时候才会发生
??注意, 如果一直fork了也不close, 那么会耗尽所有可用的文件描述符, 导致连接一直打开着
??如果我们确实想要某个TCP连接上发送一个FIN, 那么我们可以改用shutdown函数.
??如accept
, 是一个慢系统调用, 多数网络支持函数都属于这个类型. 当阻塞于慢系统调用的一个进程捕获某个信号且进入相应的处理函数的时候, 该系统调用可能返回一个EINTR
错误.(有的内核自动重启某些被中断的系统调用), 不过为了便于移植, 我们必须对EINTR
有所准备, 一个处理办法就是
while(true) {
connfd = accept(listenfd, (sockaddr_in) &clientAddr, &addrlen);
if(connfd < 0) {
if(errno == EINTR)
continue;
else perror("accept");
}
}
注意: 有一个函数我们不能这样处理, 就是connect
, 如果他出了EINTR
, 再次调用会立即返回一个错误, 我们必须用select
函数来等待连接完成
如下图的情况的时候,
如何处理这种问题依赖于不同的实现, 之后再说
??所有客户端和服务器都从调用socket开始, 客户端connect, 服务端bind, listen和accept, 大多数TCP都是并发的, 而大多数UDP却是迭代的
标签:全双工 服务 splay 知识 color unix shu odi perror
原文地址:https://www.cnblogs.com/Kimbing-Ng/p/12325965.html