【发布时间】:2012-03-24 17:02:52
【问题描述】:
我有一个维护“流式”套接字列表的程序。这些套接字被配置为非阻塞套接字。
目前,我使用一个列表来存储这些流式套接字。我有一些数据需要发送到所有这些流式套接字,因此我使用迭代器循环遍历这个流式套接字列表并调用下面的 send_TCP_NB 函数:
问题是我自己的程序缓冲区在发送到此 send_TCP_NB 函数之前存储数据的空闲大小缓慢减少,表明发送速度比将数据放入程序缓冲区的速率慢。程序缓冲区的速率约为每秒 1000 个数据。每个数据都很小,大约 100 字节。
因此,我不确定我的 send_TCP_NB 功能是否有效或正确?
int send_TCP_NB(int cs, char data[], int data_length) {
bool sent = false;
FD_ZERO(&write_flags); // initialize the writer socket set
FD_SET(cs, &write_flags); // set the write notification for the socket based on the current state of the buffer
int status;
int err;
struct timeval waitd; // set the time limit for waiting
waitd.tv_sec = 0;
waitd.tv_usec = 1000;
err = select(cs+1, NULL, &write_flags, NULL, &waitd);
if(err==0)
{
// time limit expired
printf("Time limit expired!\n");
return 0; // send failed
}
else
{
while(!sent)
{
if(FD_ISSET(cs, &write_flags))
{
FD_CLR(cs, &write_flags);
status = send(cs, data, data_length, 0);
sent = true;
}
}
int nError = WSAGetLastError();
if(nError != WSAEWOULDBLOCK && nError != 0)
{
printf("Error sending non blocking data\n");
return 0;
}
else
{
if(nError == WSAEWOULDBLOCK)
{
printf("%d\n", nError);
}
return 1;
}
}
}
【问题讨论】:
-
一点无关紧要,如果
send的返回是SOCKET_ERROR,你应该只检查WSAGetLastError。此外,send可能无法一次发送所有数据,因此在循环中调用它(增加数据指针并减小大小)直到发送所有数据。此外,确实不需要select调用,但它确实告诉您是否可以发送至少一个字节而不会阻塞。并且不需要围绕发送进行循环,如果套接字在select之后不在write_flags中,您将永远循环。 -
@JoachimPileborg 关于发送可能无法一次性发送所有内容这一事实的好点,我错过了。
标签: c++ sockets select send nonblocking