Linux TCP套接字从错误的端口接收
TCP套接字接收目标端口错误的消息时出现问题 操作系统是UbuntuLinux10.10,内核版本是2.6.31-11-rt,但其他内核也会出现这种情况。出现此问题的C/C++程序执行以下操作:Linux TCP套接字从错误的端口接收,linux,sockets,networking,Linux,Sockets,Networking,TCP套接字接收目标端口错误的消息时出现问题 操作系统是UbuntuLinux10.10,内核版本是2.6.31-11-rt,但其他内核也会出现这种情况。出现此问题的C/C++程序执行以下操作: TCP服务器套接字正在侦听端口9000处INADDR_ANY中的连接 TCP消息接收器线程通过recv(2)接收消息。读取消息后连接不会关闭,但线程将永远继续从同一连接读取 错误:TCP消息接收器还接收到发送到9000以外其他端口的消息。例如,当远程SFTP客户端连接到TCP消息接收器正在侦听的PC时,
- 同时,还有一个原始套接字监听另一个网络接口,该接口处于混杂模式。这会有影响吗
- TCP连接在消息接收之间未关闭。消息侦听器只是保持从套接字读取数据。这真的是实现TCP消息接收器的正确方法吗
/// Create TCP socket and make it listen to defined port
TcpSocket::listen() {
m_listenFd = socket(AF_INET, SOCK_STREAM, 0)
...
bzero(&m_servaddr, sizeof(sockaddr_in));
m_servaddr.sin_family = AF_INET;
m_servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
m_servaddr.sin_port = htons(9000);
bind(m_listenFd, (struct sockaddr *)&m_servaddr, sizeof(sockaddr_in);
...
listen(m_listenFd, 1024);
...
m_connectFd = accept(m_listenFd, NULL, NULL);
}
/// Receive message from TCP socket.
TcpSocket::receiveMessage() {
Uint16 receivedBytes = 0;
// get the common fixed-size message header (this is an own message structure)
Uint16 numBytes = recv(m_connectFd, msgPtr + receivedBytes, sizeof(SCommonTcpMSGHeader), MSG_WAITALL);
...
receivedBytes = numBytes;
expectedMsgLength = commonMsgHeader->m_msgLength; // commonMsgHeader is mapped to received header bytes
...
// ok to get message body
numBytes = recv(m_connectFd, msgPtr + receivedBytes, expectedMsgLength - receivedBytes, MSG_WAITALL);
}
TCP连接在消息接收之间未关闭。这个
消息侦听器只是保持从套接字读取数据。这是吗
真的是实现TCP消息接收器的正确方法吗
是,但当接收到EOS指示时,它必须关闭套接字并退出(recv()返回零)
我认为你的原始套接字和TCP套接字FD在某个地方混淆了是十分之一。嗯。。。似乎是原始套接字接收了这些消息。从日志中可以看出,是原始消息处理程序打印出消息接收内容,而不是TCP消息处理程序。嗯…!:It’对不起。因此,将原始套接字绑定到其他网络接口似乎无法正常工作。我们需要解决这个问题。有趣的是,它有时可以与SSH/SFTP一起工作,但有时不能。可能会发生其他事情(可能是从原始套接字读取,而不是从TCP套接字读取)。您会收到什么类型的“消息”,例如,当sftp客户端连接时?@nos我从中读取的套接字应该是正确的,因为它位于TCP套接字类中。原始套接字类似地位于另一个类中。不可能混淆。这些信息就是来自网络的任何数据。TCP消息处理程序类的打印输出告诉它已经收到了不应该收到的内容。顺序应该是
socket()
,bind()
,listen()
,accept()
。你的代码在做什么,你能发布相关部分吗?还有,当你说“从错误的端口接收”时,你的意思是远程端口与9000不同吗?这是正常的/预期的;在接受连接之前,您只能控制本地端口(通过bind
)。只有在通过调用getpeername()
接受后才能查询远程端口号,但不能基于远程端口号拒绝连接。@HJK25当然应该是,但给出错误/内存错误/任何可能的情况。(此外,套接字只是一个int,因此如果出于某种原因得到错误的int/缓冲区溢出,您可以轻松地从其他内容读取。您至少应该打印出正在读取的套接字文件描述符。然后通过查看该套接字描述符的/proc/the_pid/fd/进行一些调试,并将其id与输出(例如)进行比较关于netstat-APN原始套接字和TCP套接字没有混淆。问题是TCP套接字从完全错误的端口获取数据。@HJK25如果你这么说,那还可以,但我在25年的网络编程中从未见过它。我会尽可能地寻找其他解释,例如在我自己的代码中。你可以从运行完全没有原始套接字。我尝试设置原始套接字的接口(它绑定到该接口中)到非混杂模式,但似乎没有帮助。保持TCP套接字打开,即使在收到EOS后也不关闭它是否合适?我希望它打开,因为这样我可以通过已经打开的连接将数据发送到远程主机。这是可能的,还是我必须反过来,以使远程主机成为服务器和当前主机是否可以作为客户端使用?@HJK25在收到EOS后保持套接字打开是可以的,但完全没有意义。从它可以得到的只是另一个EOS,或者发送到它时出错。只有当对等方刚刚关闭它进行输出而不是关闭它时,发送到你接收到EOS的套接字才能工作。你知道吗是这样吗?