TCP套接字从错误的端口接收

3
我遇到了一个问题,TCP套接字接收消息时目标端口错误。
操作系统为Ubuntu Linux 10.10,内核版本为2.6.31-11-rt,但在其他内核中也会出现此问题。出现问题的C/C++程序执行以下步骤:
1. TCP服务器套接字正在INADDR_ANY上的9000端口侦听连接。 2. 通过TCP消息接收线程使用recv(2)接收消息。读取消息后不关闭连接,线程将继续从同一连接读取。 3. 错误:TCP消息接收器还会接收到其他端口而不是9000端口的消息。例如,当远程SFTP客户端连接到运行TCP消息接收器的PC时,它会导致TCP消息接收器也接收到SFTP消息。这怎么可能?TCP端口如何“泄漏”?我认为SFTP应该使用22号端口,对吗?那么,这些消息如何在9000端口中可见?
更多信息:
- 同时有一个原始套接字在另一个网络接口上侦听,并且接口处于混杂模式。这会产生影响吗? - TCP连接在消息接收之间未关闭。消息监听器只需从套接字读取数据即可。这真的是实现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);
}

1
很可能发生了其他事情(也许你正在从原始套接字而不是TCP套接字读取)。当sftp客户端连接时,您会收到什么样的“消息”? - nos
@nos 我读取的套接字应该是正确的,因为它在一个TCP套接字类中。原始套接字类似地在另一个类中。不可能混淆。消息只是从网络中传输的任意数据。TCP消息处理程序类的打印输出表明它收到了不应该收到的东西。 - HJK25
序列应该是 socket()bind()listen()accept()。你的代码在做什么?能否发布相关部分? - FrankH.
还有,当你说“从错误端口接收”时,你的意思是远程端口不同于9000吗?这将是正常/预期的;在接受连接之前,你只能通过 bind 控制本地端口。远程端口号只能在调用 getpeername() 之后查询,但不能根据远程端口号拒绝连接。 - FrankH.
@FrankH:m_connectFd不是静态的,但是它不需要是静态的,对吧?我可以像这样正常发送和接收消息ret = send(m_connectFd, msgPtr, msgLength, 0) - HJK25
显示剩余6条评论
2个回答

0
TCP连接在消息接收之间没有关闭。消息监听器只是从套接字中不断读取数据。这真的是实现TCP消息接收器的正确方法吗?
是的,但当它接收到EOS指示(recv()返回零)时,必须关闭套接字并退出。
我认为你的原始套接字和TCP套接字FDs在某个地方混淆了。

原始套接字和TCP套接字不会混淆。问题是TCP套接字从完全错误的端口获取数据。 - HJK25
@HJK25 好的,如果你这么说的话,但我在 25 年的网络编程中从未见过它。我会尽可能地寻找其他解释,比如在我的代码中。你可以先尝试不使用原始套接字来运行。 - user207421
我尝试将原始套接字的接口(它已绑定到该接口)设置为非混杂模式,但似乎没有帮助。即使在收到EOS后,保持TCP套接字打开而不关闭它是否可以?我想保持它打开,因为这样我就可以通过已经打开的连接向远程主机发送数据。这是可能的吗,还是我必须将其反过来,使远程主机成为服务器,而此当前主机将作为客户端工作? - HJK25
@HJK25,保持套接字在收到EOS后仍然打开是完全没有意义的。你只能从中获得另一个EOS,或者在向其发送数据时出现错误。如果你已经收到了EOS,那么向套接字发送数据只有在对等方刚刚关闭输出而不是关闭套接字的情况下才能起作用。你知道这是这种情况吗? - user207421

0

嗯...看起来最终接收到消息的是原始套接字。从日志中可以看到,打印出消息接收内容的是原始消息处理程序,而不是TCP消息处理程序。唉...!:S 抱歉。因此,似乎将原始套接字绑定到其他网络接口上的操作没有正确执行。需要修复这个问题。有趣的是,有时候它可以使用SSH/SFTP,有时候则不行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接