c - 通过 TCP-IPv6 连接进行数据传输

标签 c tcp network-programming client-server ipv6

我正在使用 C 语言和 Linux 平台开发客户端-服务器应用程序。我想要实现的是在客户端和服务器上通过 TCP 连接更改套接字 ID 而不会丢失数据,其中客户端将数据从文件发送到主线程中的服务器。该应用程序是多线程的,其中其他线程根据某些全局标志集更改套接字 ID。

问题:应用程序通过 IPv4 和 IPv6 路径建立了两个 TCP 套接字连接。我首先在主线程中通过 TCP-IPv4 连接传输文件。另一个线程正在检查一些全局标志,并且可以访问/共享为主线程中的每个协议(protocol)创建的套接字 ID。 send 和 recv 在其调用中使用指针变量来指向要用于数据传输的套接字 ID。数据最初通过 TCP-Ipv4 传输。一旦设置了全局标志并且几乎没有进行其他检查,另一个线程就会更改发送调用中使用的套接字 ID 以指向 IPv6 套接字。该线程还负责传达两台主机之间的变化。我在切换之前通过 IPv4 完全发送了所有数据。在刚刚切换套接字 ID 后,我还通过 Ipv6 发送数据。但是在传输过程中,通过 IPv6 连接丢失了数据。(我在服务器端 send(*p_dataSocket.socket_id,sentence,p_size,0); 的发送函数中使用指针变量来更改指向动态 IPv6 套接字 ID 的指针)

在 recv 和 send 调用之后的错误分别是 ESPIPE:Illegal seek,但是这个错误甚至在切换之前就存在了。所以我非常确定这与数据丢失无关

我正在使用 pselect() 检查每个套接字的可用数据。我能以某种方式理解切换时的数据丢失(如果处理不当),但我无法弄清楚为什么在切换后传输过程中会发生数据丢失。我希望我清楚问题是什么。我还检查了在不切换的情况下通过每个协议(protocol)单独发送数据并且没有数据丢失。我最初通过 Ipv6 传输数据然后切换到 IPv4,没有数据丢失。也非常希望知道除了使用 errnonetstat 之外如何调查此问题。

最佳答案

当您使用 TCP 发送数据时,您不能丢失中间的部分信息。您要么按照发送方式接收字节流,要么什么也接收不到——前提是您正确使用了与套接字相关的函数。

您可能需要调查几个要点。

  • 首先,您必须确保您真正发送的是丢失的数据。在服务器端应用程序上添加一些日志记录:将您使用 send() 传输的任何内容转储到某个文件中。还包括一些额外的信息,例如:

    数据包编号==1234,*p_dataSocket.socket_id==11,Data==“data_contents_here”,共22字节;发送()返回==22

这里重要的是看*p_dataSocket.socket_id的内容。确保您使用的是互斥锁或类似的东西,因为您有一个定期读取 socket_id 内容的线程和另一个偶尔更改它的线程。除非您的线程在读/写时可以独占访问该地址,否则不能保证您不会从该地址获取错误值。这对于程序的正常运行和调试信息的生成都很重要。

这里另一个可能的问题是选择sentence 发送的逻辑。在多线程程序中可能很难跟踪此变量的损坏。传输信息的记录也会在这方面为您提供帮助。

  • 使用任何 TCP 嗅探器检查 TCP 堆栈真正传输的内容。是否有丢失数据的数据包?如果没有这些数据包,请尝试找出哪个 send() 调用负责发送该数据。如果存在这些数据包,请检查接收端是否存在错误。

  • errno 值不应单独使用。只有当你从一个函数中得到一个错误的返回时,它的值才有意义。尝试找出 errno 何时变为 ESPIPE 这可能发生在任何 API 函数返回类似 -1 的内容(取决于函数)时。当您发现它发生的位置时,您应该找出那段特定代码中的错误(调试器是您的 friend )。请记住,多线程环境中的 errno 行为取决于您的系统实现。确保您使用 -pthread 选项 (gcc) 或至少使用 -D_REENTRANT 进行编译以将风险降至最低。

  • 检查 this question有关 errno==ESPIPE 情况的可能原因的一些信息。按照那里的建议尝试一些调试技术。 ESPIPE 的 Errno 值提示您在程序的某处错误地使用了文件描述符。也许在某个地方您正在使用套接字 fd 作为常规文件或类似的东西。这可能是由某些竞争条件(多个线程同时访问一个对象)引起的。

关于c - 通过 TCP-IPv6 连接进行数据传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8632478/

相关文章:

c - 为什么 4 线程程序在 1 核 VM 上比在 4 核 VM 上运行得更快?

可以在 "main"之前调用函数吗?如果是这样,会发生什么?

java - 发送到 ServerHandler 外部时,客户端未收到服务器发送的消息

java - 使用 Applet 获取客户端 MAC ID 时出现问题

c++ - 使用 NEW 而不是 MALLOC 的 GetAdapterAddresses 函数

c++ - 如何通过本地 LAN 使用网络别名自动访问嵌入式设备的 Web 服务器?

c - 在 C 中设置环境变量

c - 在虚拟 shell 中处理 CTRL-C

macos - 如何在 mac 中通过进程名称捕获网络流量?

c++ - TCP没有收到发送的数据