发送一定量的字节后,插座发送()悬挂
socket send() hangs after sending certain amount of bytes
我想向我的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
(我看不到这些值之间的连接(
,我可以看到您应该参加一些问题:
- 您正在尝试将许多消息发送到客户的期间代码,但是您没有检查是否存在错误可变
sendResult
。请在发送另一个之前检查一下消息。 - 您正在使用相同的线程发送数据并检查具有无限循环发送每个消息的间隔,它会消耗大量CPU。我建议创建一个线程( tsync (以使用
sleep
或std::chrono
参加间隔,并调用一种通过套接字发送消息的方法,但不是在同一线程中 tsync 您将用睡眠阻塞插座。 - 最后,您应该使用
FD_SET
和select
检查何时可以通过插座发送数据,何时准备发送更多字节。
可能是您在没有控制的情况下发送消息的方式可能会影响TX通道,因为它已被整理,因此您应该使用FD_SET
和select
控制输出操作,以与套接字同步。在写作的情况下,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;
}
- 避免在基于反向范围的for循环实现中悬挂参考
- 是否可以检查悬挂光纤的调用堆栈?
- 蓝牙插座只能读取一次,为什么?
- Asio端接插座功能:取消、关闭、关闭、释放
- 提升 ASIO 打开多个插座
- 网络插座 |无法设置on_close/打开处理程序
- ZMQ:连接 ZMQ 插座时"Resource temporarily unavailable"
- 如何通过插座传输 ESP32-Cam 拍摄的图像?
- UDP客户端/服务器程序在不同的IP和端口上通信超过2个插座
- PTHREAD_JOIN()似乎导致我的程序悬挂,它在哪里弄错了
- 如何通过pthread发送插座ID
- TOS字段从Linux的TCP插座上接收到的数据包获取
- 程序悬挂,不循环
- 睡眠:(睡眠或usleep)并没有将我的线程中的所有内容悬挂在Linux中,而是在Windows中悬挂吗?为什么
- C UDP RecvFrom最终悬挂在远程连接上
- 不同网络之间的插座编程
- 如何通过1024字节缓冲区和强力冲洗在插座连接上发送6个字符的C弦
- Python/C 远程TCP插座
- 我可以使用Windows上使用ASIO(非凸轮)打开2048个插座
- 发送一定量的字节后,插座发送()悬挂