我正在学习Unix网络编程第1卷,我想重现Linux中RST的接受错误。
socket()
,bind()
,listen()
和sleep(10)
socket()
,connect()
和setsockopt()
中的LINGER
,close()
,return
accept()
我认为第3步会出现类似ECONNABORTED
的错误,但不会。
我想知道为什么吗?
如果您能帮助我,我将不胜感激。
以下是服务器code
:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
bind(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));
listen(sock, 5);
sleep(10);
if (accept(sock, NULL, NULL) < 0)
perror("error");
else
printf("right");
return 0;
}
以下是客户端code
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
connect(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));
struct linger ling;
ling.l_onoff = 1;
ling.l_linger = 0;
setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof ling);
close(sock);
return 0;
}
答案 0 :(得分:2)
不。我认为您将获得一个空的但完整的连接(无数据)。内核将管理完整的连接建立,然后将立即获得FIN数据包(意味着EOF,而不是重置)并对其进行处理(或等待用户空间进程关闭其一侧,以将FIN发送到另一侧)对于连接中止,您需要在不允许客户端发送FIN数据包的情况下重新引导客户端计算机(或服务器)(或在重新引导计算机之前将其与网络断开连接)不会收到来自ACK的RST。
当两方之间存在某些状态不匹配时,内核会自动发送RST数据包。为了使这种情况在正确的实现中发生,您必须强制这种状态不匹配(这就是为什么必须重新启动计算机的原因)
获取RST段的其他方法包括TCP的错误实现或处理传输中的数据包(更改传输中的发送方或接收方序列号)
RST数据包的目的不是向TCP添加功能,而是检测错误行为,因此,没有任何方法可以通过正确使用套接字来进行重置。 Listen syscall可以让您在内核空间中保留资源,以允许用户空间进程准备在客户端尝试连接时处理连接。如果您执行了您打算的操作,那么将得到一个没有数据的连接,但有一个有效的连接,当机器没有时间互相发送数据包时,SO_LINGER
会强制失去状态。 ...,但已连接,整个连接都在内核中处理,并且不会中止。
答案 1 :(得分:0)
Linux accept()(和accept4())传递已经挂起的网络错误 在新套接字上作为来自accept()的错误代码。这种行为 与其他BSD套接字实现不同。为了可靠 操作应用程序应该检测到定义的网络错误 for accept()之后的协议,并通过 重试。对于TCP / IP,它们是ENETDOWN,EPROTO, ENOPROTOOPT,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPP和 ENETUNREACH。