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

时间:2011-12-26 01:36:26

标签: c tcp network-programming client-server ipv6

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

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

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

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

1 个答案:

答案 0 :(得分:1)

当您使用TCP发送数据时,您无法在之间丢失部分信息。您可以按发送方式接收字节流,也可以根本不接收任何内容:只要您正确使用与套接字相关的功能。

您可能需要调查几点。

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

    数据包编号== 1234,* p_dataSocket.socket_id == 11,数据==“data_contents_here”,总共22个字节; send()return == 22

这里重要的是观看*p_dataSocket.socket_id的内容。确保您使用互斥锁或其他类似的东西导致您有一个定期读取socket_id内容的线程和另一个偶尔会更改它的线程。除非您的线程在读/写时拥有垄断权限,否则您无需担心从该地址获取错误的值。对于正常的程序操作和调试信息的生成都很重要。

此处另一个可能的问题是选择sentence发送的逻辑。在多线程程序中,可能难以跟踪此变量的损坏。传输信息的记录也会对您有所帮助。

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

  • errno值不应单独使用。只有当你从函数中得到错误的返回时,它的值才有意义。尝试找出确切的errno何时成为ESPIPE当任何API函数返回-1之类的东西(取决于函数)时,可能会发生这种情况。当你发现它发生的地方时,你应该找出那段特定代码中的错误(调试器是你的朋友)。请记住,多线程环境中的errno行为取决于您的系统实现。确保使用-pthread选项(gcc)或至少使用-D_REENTRANT编译以最小化风险。

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