发送一定量的字节后,插座发送()悬挂

socket send() hangs after sending certain amount of bytes

本文关键字:悬挂 插座 一定量 字节      更新时间:2023-10-16

我想向我的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): %dn", 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: %dn", 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. 您正在尝试将许多消息发送到客户的期间代码,但是您没有检查是否存在错误可变sendResult 。请在发送另一个之前检查一下消息。
  2. 您正在使用相同的线程发送数据并检查具有无限循环发送每个消息的间隔,它会消耗大量CPU。我建议创建一个线程( tsync (以使用sleepstd::chrono参加间隔,并调用一种通过套接字发送消息的方法,但不是在同一线程中 tsync 您将用睡眠阻塞插座。
  3. 最后,您应该使用FD_SETselect检查何时可以通过插座发送数据,何时准备发送更多字节。

可能是您在没有控制的情况下发送消息的方式可能会影响TX通道,因为它已被整理,因此您应该使用FD_SETselect控制输出操作,以与套接字同步。在写作的情况下,Microsoft文档说:

选择功能用于确定一个或多个插座的状态。对于每个插座,呼叫者可以请求有关读取,写或错误状态的信息。

writefds :可以发送数据。

已更新,4月21日:我建议您分享有关您的问题的更多信息,例如服务器的代码和配置,以了解是否有一些时间的配置或缓冲区大小。您提供的信息还不够,并且不会像我们这样提出的请求来降低我们的要求:

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

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

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

所以,此刻,这就是我可以为您提供帮助的全部。

更新4月24日:尝试以下步骤控制套接字变速器并设置 non-Blocing 套接字:

  • 获得成功的连接后,在客户端中,将套接字设置为非阻滞。

  • 在循环文件描述符(FD_SET(和select中使用以检查套接字何时准备编写。

您的代码应具有以下代码:

void ConnectToServer()
{
    //... your code
    int connectResult = ::connect(sock, (struct sockaddr *)&server, sizeof(server));
    if (connectResult >= 0)
    {
        u_long iMode = 1;
        int iResult = ioctlsocket(sock, FIONBIO, &iMode); //Set the socket Non-Blocking
        printf("Connected to server!n");
    }
    else
    {
        printf("Not connected to server. Err: %dn", connectResult);
    }
}
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;

    fd_set write_fd;
    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";
            FD_ZERO(&write_fd); //Reset the File Descriptor
            FD_SET(sock, &write_fd); //Set se File descriptor to the socket.
            int result = select(max_sd, NULL, &write_fd, NULL, NULL);   //Wait until the socket is ready to write
            if (result < 0)
            {
                iprintf("There was a problem with the sockets reading.n");
                FD_ZERO(&write_fd);
            }
            int sendResult = ::send(sock, request.c_str(), request.length(), 0);
            iprintf("req(%d): %dn", nMsgSent, sendResult);
            nMsgSent++;
            lastSendTime = now;
        }
    }
    return 0;
}