TCP 代理接收数据阻塞问题解决方案

本文详细解析了TCP代理在处理客户端与服务器间数据转发的工作原理。通过示例阐述了如何利用select函数解决数据接收不完整及阻塞问题,确保数据能够正确且及时地在两端进行传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TCP 代理转发数据示意图如下:

                 Client <--------------------------->TCP Proxy <---------------------------->Server

Client 先发起请求,代理在接收到connect 请求之后,新建一个线程处理该客户端的转发需求。

在调用recv 接收数据时,有时程序会一直阻塞在那里,原因是socket 默认是阻塞模式,而当前没有数据可接收时会一直等待。还有另一个情况:调用一次recv, 数据并没有接收完全,再调用recv 时仍然会阻塞。在应用层除非明确知道结束标志或者数据长度,否则没法知道数据是否已接收完毕。

 

正确的做法是轮询,使用select 实现,当某个socket处于可以接收时,就去读取数据,然后用另一个socket 转发。

实现的方法:

fd_set readfds;

TIMEVAL tv;

tv.tv_usec = 100;

tv.tv_sec = 1;

do{

    FD_ZERO(&readfds);

    FD_SET(socket_client, &readfds);

    FD_SET(socket_server, &readfds);

    int n = select(0, &readfds, NULL, NULL, &tv);

    if (n>0)  //有数据可读
    {
        if (FD_ISSET(socket_client, &readfds))
        {

            int nr = recv(socket_client, buffer, buffer_size, 0);

            if (nr > 0)

                int ns = send(socket_server, buffer, nr, 0);
        }

     
        if (FD_ISSET(socket_server, &readfds))
        {
            int nr = recv(socket_server, buffer, buffer_size, 0);
            if (nr > 0)
                int ns = send(socket_client, buffer, nr, 0);

        }
    }

    else if (n == SOCKET_ERROR) //选择错误
    { 
         printf("select error");
         break;
    }

    else  //超时,Sleep 1s
    {
        Sleep(1000);
    }

}while(true);

参考:

https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值