socket send()在发送一定数量的字节后挂起

时间:2017-04-19 17:06:53

标签: c++ sockets tcp

我想将一个字符串发送到我的nodejs TCP服务器。

这是我的客户端代码(C ++):

#include <nds.h>
#include <dswifi9.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string>

std::string hostname = "hostname";
int port = 61733;
int sock;

int main(){
    Connect(); //function to connect with a WiFi network
    ConnectToServer();

    unsigned long lastSendTime = 0;
    unsigned long sendInterval = 200; //send a message every 200 milliseconds
    unsigned int nMsgSent = 0;

    while (1){
        unsigned long now = milliseconds(); //function to get the time in milliseconds
        if ((now - lastSendTime) > sendInterval){
            std::string request = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            request += request;
            request += std::to_string(nMsgSent);
            request += "\n";

            int sendResult = ::send(sock, request.c_str(), request.length(), 0);
            iprintf("req(%d): %d\n", nMsgSent, sendResult);

            nMsgSent++;
            lastSendTime = now;
        }
    }
    return 0;
}

这是我的服务器代码(JS):

var net = require('net');

var tcpServer = net.createServer();  
var tcpPort = 61733;

tcpServer.on('connection', onConnection);

function onConnection(conn){  
  var remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
  console.log('New client connection from: %s', remoteAddress);

  conn.on('data', onData);
  conn.once('close', onClose);
  conn.on('error', onError);

  function onData(data){
    console.log('connection data from %s: %s', remoteAddress, data);
  }

  function onClose(){
    console.log('connection from %s closed', remoteAddress);
  }

  function onError(err){
    console.log('Connection %s error: %s', remoteAddress, err.message);
  }
}

tcpServer.listen(tcpPort, function(){  
  console.log('Server listening on: %j', tcpServer.address());
});

问题出现了:

客户端仅发送大约180条消息,然后send挂起。服务器只接收~120条消息。当我增加请求的长度时,客户端发送的请求减少,当我减少长度时,客户端发送更多请求。我还发现当我减少sendInterval时,我可以在send挂起之前发送更多请求。我不知道自己做错了什么。当我使用nodejs客户端执行类似的代码时,一切都很好,所以问题在于C ++客户端。

编辑:

我并不认为这是必要的,但这里是connectToServer()的代码:

void ConnectToServer()
{
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (socket >= 0)
    {
        printf("Created Socket!\n");
    }
    else
    {
        printf("Couldn't create socket");
    }

    struct hostent * host = gethostbyname(hostname.c_str());
    if (host != NULL)
    {
        printf("Found IP Address!\n");
    }
    else
    {
        printf("IP not found");
    }   

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = *((unsigned long *)(host->h_addr_list[0]));

    int connectResult = ::connect(sock, (struct sockaddr *)&server, sizeof(server));
    if (connectResult >= 0)
    {
        printf("Connected to server!\n");
    }
    else
    {
        printf("Not connected to server. Err: %d\n", connectResult);
    }   
}

C ++客户端的输出(发送间隔:2000ms,msgLength:126-127个字符):

req(1): 126
req(2: 126
req(3): 126
...keeps going on for a while...
req(9): 126
req(10): 126
req(11): 127
req(12): 127
...keeps going on for a while...
req(74): 64
send() hangs after this

来自nodejs服务器的输出(仅接收9条消息):

connection data from ip::port: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678900

...keeps going on for a while...

connection data from ip::port: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678909

测试结果以查看发送间隔,消息长度和已发送消息数之间是否存在连接:

 sendInterval |  msgLength  |   nMsg
---------------------------------------
     200      |    127      |    26
     200      |    65       |    33
---------------------------------------
     400      |    65       |    59
     400      |    127      |    53
---------------------------------------
     2000     |    65       |    47
     2000     |    127      |    21

(我没有看到这些值之间的联系)

1 个答案:

答案 0 :(得分:0)

我可以看到你应该参加一些问题:

  1. 您正在尝试向客户端发送许多消息 代码,但你没有检查是否有错误,使用 变量sendResult。在发送另一个之前应该检查它 消息。
  2. 您正在使用相同的线程发送数据并检查具有无限循环的间隔来发送每条消息,它消耗了大量的CPU。我建议创建一个线程( TSync )来参加sleepstd::chrono的间隔,并调用一个按套接字发送消息但不在同一个线程中的方法< em> TSync 因为你将使用sleeps来阻止套接字。
  3. 最后,当套接字准备发送更多字节时,您应该使用FD_SETselect来检查何时可以通过套接字发送数据。
  4. 可能是您无控制地发送消息的方式会影响TX通道,因为它正在变得充满所以您应该使用FD_SET和{{1}来控制输出操作与套接字同步。在写的情况下,Microsoft documentation说:

      

    select函数用于确定一个或多个套接字的状态。对于每个套接字,调用者可以请求有关读,写或错误状态的信息。

         

    writefds :可以发送数据。

    更新,4月21日:我建议您分享有关您的问题的更多信息,例如服务器的代码和配置,以了解是否配置了超时或缓冲区大小。您提供的信息是不够的,并没有低估我们向您发出的请求,如此评论:

      

    我真的不认为这是必要的,但这里是connectToServer()的代码:

    连接过程很重要,因为我们可以看到套接字服务器是否设置了一些选项。

    在这种情况下,您与我们分享的所有信息都可能有所帮助,而不是假设这不重要。

    所以,在这一刻,这就是我可以帮助你的一切。

    4月24日更新:尝试以下步骤来控制套接字传输并设置 NON-Blocing 套接字:

    • 连接成功后,在客户端中将套接字设置为NON-BLOCKING。

    • 在循环文件描述符(select)和FD_SET中使用,以检查套接字何时可以写入。

    您的代码应该包含以下代码:

    select