1. 为什么产生?当send 在 事件选择 模式下, 成为非堵塞函数,一旦 系统缓存下的时候,就会产生这个错误。那么,recv 何时会产生类似错误呢? 不会也是系统缓存也不够吧。
2. 产生的时候,如何解决? char buf[buffSize];
ZeroMemory(buf,buffSize);
strcpy(buf,"hello");
while(1)
{
int nbytes=send(s,buf,buffSize,0);
//检测错误,处理 系统缓存不够的情形
if( (nbytes==SOCKET_ERROR) && ( GetLastError()==WSAEWOULDBLOCK) )
{
WaitForSingleObject(event1,-1); //这个是我写的,我其实不知道其何时有信号? 时间该设置多久何时呢?
// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
WSANETWORKEVENTS event;
::WSAEnumNetworkEvents(s, event1, &event);
if(event.lNetworkEvents & FD_READ) // 处理FD_READ通知消息
{
if(event.iErrorCode[FD_READ_BIT] == 0)
{}
}
else if(event.lNetworkEvents & FD_CLOSE) // 处理FD_CLOSE通知消息
{
if(event.iErrorCode[FD_CLOSE_BIT] == 0)
{
::closesocket(s);
break;
}
}
// 这个才是重点, 处理 系统缓存有空闲了,这里也是 本帖的疑问处:
以下代码是我写的,我感觉不对,比如:nbytest一旦是-1的时候,就悲剧了。 还有,如果以下代码中send再次 错误,该如何啊。
else if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息
{
if(event.iErrorCode[FD_WRITE_BIT] == 0)
{
//继续发送上次的
char* p=buf+nbytes;
nbytes=send(s,buf,buffSize-nbytes,0);
}
}
}
Sleep(500); //定时器的作用
}
2. 产生的时候,如何解决? char buf[buffSize];
ZeroMemory(buf,buffSize);
strcpy(buf,"hello");
while(1)
{
int nbytes=send(s,buf,buffSize,0);
//检测错误,处理 系统缓存不够的情形
if( (nbytes==SOCKET_ERROR) && ( GetLastError()==WSAEWOULDBLOCK) )
{
WaitForSingleObject(event1,-1); //这个是我写的,我其实不知道其何时有信号? 时间该设置多久何时呢?
// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
WSANETWORKEVENTS event;
::WSAEnumNetworkEvents(s, event1, &event);
if(event.lNetworkEvents & FD_READ) // 处理FD_READ通知消息
{
if(event.iErrorCode[FD_READ_BIT] == 0)
{}
}
else if(event.lNetworkEvents & FD_CLOSE) // 处理FD_CLOSE通知消息
{
if(event.iErrorCode[FD_CLOSE_BIT] == 0)
{
::closesocket(s);
break;
}
}
// 这个才是重点, 处理 系统缓存有空闲了,这里也是 本帖的疑问处:
以下代码是我写的,我感觉不对,比如:nbytest一旦是-1的时候,就悲剧了。 还有,如果以下代码中send再次 错误,该如何啊。
else if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息
{
if(event.iErrorCode[FD_WRITE_BIT] == 0)
{
//继续发送上次的
char* p=buf+nbytes;
nbytes=send(s,buf,buffSize-nbytes,0);
}
}
}
Sleep(500); //定时器的作用
}
不是错误, 那么 recv调用后,getlasterror会产生这个?send是因为系统缓存不够导致的,能理解那recv呢?
“char* p=buf+nbytes;
nbytes=send(s,buf,buffSize-nbytes,0);”而不应该接着再发吧。
--------------
不是,可能是没有数据,非阻塞IO模型下,,所以你不能以recv的返回值作为判断依据,需要看WSAGetLastError的返回值来判断其真正的原因。你需要用其它机制来判断数据到来,然后调用recv,将数据从系统缓冲区copy到用户缓冲区中。
我的问题在于: 1. WaitForSingleObject(event1,-1); //这个是我写的,我其实不知道其何时有信号? 时间该设置多久何时呢?
2.// 这个才是重点, 处理 系统缓存有空闲了,这里也是 本帖的疑问处:
以下代码是我写的,我感觉不对,比如:nbytest一旦是-1的时候,就悲剧了。 还有,如果以下代码中send再次 错误,该如何啊。
else if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息
{
if(event.iErrorCode[FD_WRITE_BIT] == 0)
{
//继续发送上次的
char* p=buf+nbytes;
nbytes=send(s,buf,buffSize-nbytes,0);
}
}
char buf[buffSize];
ZeroMemory(buf,buffSize);
strcpy(buf,"hello");
while(1)
{
int nbytes=send(s,buf,buffSize,0);
//检测错误,处理 系统缓存不够的情形
if( (nbytes==SOCKET_ERROR) && ( GetLastError()==WSAEWOULDBLOCK) )
{
WaitForSingleObject(event1,-1); //这个是我写的,我其实不知道其何时有信号? 时间该设置多久何时呢?
// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
WSANETWORKEVENTS event;
::WSAEnumNetworkEvents(s, event1, &event);
WaitForSingleObject(event1,-1); //这个是我写的,我其实不知道其何时有信号? 时间该设置多久何时呢?
这个地方你应该是对这个socket注册了一个事件,等相应的read,write的时候,你将这个事件set
而在非堵塞模式下,就会返回这个错误码。
当send 在 事件选择 模式下, 成为非堵塞函数,一旦 系统缓存下的时候,就会产生这个错误。
这句话修改一下,不是错误,是错误码。
1.按你的代码逻辑,肯定是到了发送缓冲区被写满了,才会进入你的if条件中。(当然,还有一种产生WSAEWOULDBLOCK错误的情况,这里不用考虑)
2.WaitForSingleObject(event1,-1);是等待注册的套接字上有读、写、关闭事件的时候才会激活,放在这个位置是不合适的。因为你已经调用了send。也就是说信号已经受信了。
3.你做的这个实际已经类似于异步通信了(只是我的理解)。应该在另外一个线程中WaitForSingleObject(event1,-1);然后做你下面的所有操作。
4.当if( (nbytes==SOCKET_ERROR) && ( GetLastError()==WSAEWOULDBLOCK) )这个发生的时候,你应该暂停你的while循环,做相应的错误处理。
回复你的第2点:放在这里,位置不对, 我却是不知道放哪里合适。需求: 连接后,就隔几秒钟发送一次数据包。 这个是需求。如果错误,我们处理错误。所以send放在while中是由道理的。但是:你第一次发送数据,是你主动发送出去, 岂能调用等待函数呢?肯定不能把 send和等待函数位置交换。就好比, 程序启动后,连接服务单,然后发送数据,第一次发送时候, 如果等待函数在前,send在后, 你说说,等待函数会返回嘛? 怕是很难的。因为没有信号, 计算机怎么就知道何时有信号呢,你只是连接了,没有调用send,这个信号怎么会平白无故诞生呢? 尽管注册了这个事件, 和服务器保持连接了,信号不会凭空而降。所以我把等待函数放在send后面.
第3点: 没有2个线程,只有一个
第4点:你看了没,我已经处理错误了。
else if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息
{
if(event.iErrorCode[FD_WRITE_BIT] == 0)
{
//继续发送上次的
char* p=buf+nbytes;
nbytes=send(s,buf,buffSize-nbytes,0);
}
}
这个难道不是错误处理吗?当然,我的有些问题存在,更正一下,这个套接字,只有2个事件被注册:FD_WRITE, FD_CLOSE , 没有其他事件。 原因是,在这个线程里,我要处理,主动发送数据,如果遭遇了 WSAEWOULDBLOCK,该如何处理错误的问题。 这是需求,目标啊。
程序只将套接字注册了事件, 然后连接服务器,其他函数不调用,只调用等待函数, windows可以做到, FD_WRITE产生吗?是不可以的!调用send 可能会产生 FD_WRITE, 但是不调用send, 不可能产生该事件。所以我才搞不懂,这个需求,到底该如何实现啊?谁能提供代码?
ZeroMemory(buf,buffSize);
strcpy(buf,"hello");
buffSize = sizeof(buf); //这里的发送字符大小应该是等于数据大小“char* p=buf+nbytes;
nbytes=send(s,buf,buffSize-nbytes,0); ”这两句这样修改一下:
int nPreBytes = 0;
while(1)
{
....
if( (nbytes==SOCKET_ERROR) && ( GetLastError()==WSAEWOULDBLOCK) )
{
....
char* p=buf+nPreBytes;
nbytes=send(s,buf,buffSize-nPrebytes,0);
if(nbytes > 0 && nbytes < (buffSize-nPreBytes))
{
nPreBytes = nbytes;
}
}else
{
nPreBytes = nbytes;
}
}
if(nbytes > 0 && nbytes < (buffSize-nPreBytes))
{
nPreBytes = nbytes;
}
}else
{
nPreBytes = nbytes;
}if.......else里 的没有看懂2. 我终于发现这个算法 怕是无穷的算法了。请我听一言,让我慢慢道来:当你在FD_WRITE 里再次调用send的时候, 如果再次失败,咋整。貌似这个算法 是很难完成的。while循环开头就有个send如果再次 一旦遇到FD_WRITE ,那么就说明没有完整发送出去,自然得做处理了。
处理过程中,又再 产生WSAEWOULD, 玩完,这个是什么算法嘛。还有:send 如果成功发送, 也有可能发送了部分,未必就是WSAEWOULD。这个算法太难了。
服务端:接受数据
while(TRUE)
{
nRet = recv(Clientsock,Recbuf1,MAX_PATH,0);
if(nRet <= 0 )break; }
客户端发送:nRet = send(Clientsock,"liujiquan has comming!",MAX_PATH/2,0);
nRet = send(Clientsock,"123!",MAX_PATH/2,0);
nRet = send(Clientsock,"22222222222!",MAX_PATH,0);经watch框里面,我貌似只能接收到 "liujiquan has comming!", 和 ,"22222222222!", 起始不然。
第一次 recv的Recbuf1 显示"liujiquan has comming!", 但是起始你会发现
Recbuf1[Recbuf1[MAX_PATH/2]] = '1';
Recbuf1[Recbuf1[MAX_PATH/2+1]] = '2';
Recbuf1[Recbuf1[MAX_PATH/2+2]] = '3';所以你的数据其实是获取到了。
因为你send的数据大小 为MAX_PATH/2 ,MAX_PATH/2,MAX_PATH 。
所以一般最好服务和客户端 发送接收大小 保持一致就不出出现这个疑问;
还有 GetLasetError = WSAEWouldBock 仅仅只是表示 没有数据 可以recv而已。
不是错误。