socket send()成功却发不出数据

问题描述

有一个SMB的代理程序,大多数情况下能正常运行,但是,有时候会出现传输速度降为0的情况(持续一分钟左右,恢复正常)
排查是代理程序中socket的send()函数执行成功,但是抓包发现没有发出数据包。
说明: 这个现象不是经常出现,我传了1000左右文件出现一两次。

问题出现的环境背景及自己尝试过哪些方法

语言:C
环境:Debian 8.8
使用抓包软件抓客户端,代理,服务器的协议包。
1.1、客户端发送Request后没有收到Response,但是从SMB服务端的抓包看,服务端发送了Response的。
1.2、然后我在代理程序中套接字发送数据部分加了打印。send(),显示已经成功运行了。可是代理程序的抓包中没有抓到Response信息。
也就是说代理收到了Request后也转发了Response。
结论: 出现速度为0的原因应该是smb客户端收不到Response导致超时,重新和smb端连接。而恢复了连接。

2、在速度变为0时,执行了netstat -tnap 并没有发现发送队列里没有未发送出去的数据。

你期待的结果是什么?实际看到的错误信息又是什么?

请教这个问题到这该从哪里下手。。。。

阅读 7.7k
1 个回答

完整代码不方便贴出来,贴出了简化的部分代码。省掉了日志,smb协议处理的配置。
程序是使用的TCP传输。

1.
我发现如果把smb内容处理函数注释掉,只是透传的话是完全正常的。
但是deal_with_smb()这个函数只是处理了收发字符串。
2.
再次复现问题,抓包。这次抓所有tcp包。看是不是有处理错误的协议,导致客户端解释不了丢掉了。结果代理这边并没有发出异常的tcp包。

有思路么,有思路么,有思路么,
谁能提供个查错的思路,感谢

void *do_smb_proxy (void *param)
{
    /* 屏蔽信号SIGPIPE*/  
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGPIPE);
    pthread_sigmask(SIG_BLOCK, &mask, NULL);
    
    struct parse_result *result;
    result = (struct parse_result)malloc(sizeof(struct parse_result));

    int usersockfd = (struct session)param->usersockfd;
    int isosockfd = (struct session)param->isosockfd;

    userbuf = (char *)malloc(maxsize);
    // 错误处理
    serverbuf = (char *)malloc(maxsize);
    // 错误处理

    while (1)
    {
        // 监听用户端和服务端套接字
        FD_ZERO (&rdfdset);
        FD_SET (usersockfd, &rdfdset);
        FD_SET (isosockfd, &rdfdset);
        dbg("*****wait the message*********\n");    
        if (select (FD_SETSIZE, &rdfdset, NULL, NULL, NULL) < 0)
        {
            goto Error;
        }
    
        if (FD_ISSET (usersockfd, &rdfdset))
        {
            memset(userbuf, 0, maxsize);
            if ((useriolen = read (usersockfd, userbuf, maxsize)) <= 0)
            {
                goto Error;
            }
#if 1
            // result 中存储的处理完要回复给服务器的数据结构体。不是smb协议什么也不做
            ret = deal_with_smb(userbuf, useriolen, result);  
            if ( 0 > ret )
            {
                goto Error;
            }            
            _smb_response(usersockfd, result);
#else
            // 收到的信息直接发送给server
            ret = _server_write(_server_sock, userbuf, useriolen);
            if ( 0 >= ret )
            {
                goto Error;
            }
#endif
        }
        // 接收服务端的套接字,解析协议数据并发送给客户端。
        // 总是在这里出现发送数据成功后却抓包抓不到发送的数据。
        if(FD_ISSET (isosockfd, &rdfdset)) 
        {
            memset(serverbuf, 0, maxsize);
            isoiolen = _server_read(_server_sock, serverbuf, maxsize);
            if ( 0 >= isoiolen )
            {
                goto Error;
            }
#if 1
            // result 中存储的处理完要回复给客户端的数据结构体,不是smb协议什么也不做
            ret = ret = deal_with_smb(_server_sock, isoiolen, result);
            if ( 0 > ret )
            {
                goto Error;
            }
            _smb_response2(_server_sock, result); // 回复
#else
            ret = write(usersockfd, serverbuf, isoiolen);
            if ( 0 >= ret )
            {
                goto Error;
            }
#endif
        }
    }
Error:
    ......// 释放占用资源
    return NULL;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题