首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Windows writeFileEx和recvfrom Crashes程序

Windows writeFileEx和recvfrom Crashes程序
EN

Stack Overflow用户
提问于 2013-08-09 18:00:39
回答 2查看 330关注 0票数 0

我正在试着写一个非常简单的C程序。由于某些原因,我不能在同一个程序中使用writeFileEx和recvfrom,因为每次调用writeFileEx都会导致recvfrom崩溃。

下面是相关的代码片段

代码语言:javascript
复制
struct sockaddr_in server, client_address;
int client_length, recv_len;
char buf[BUFLEN];
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0 )
{
  //Error
}

SOCKET s = socket (AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
{
 //invalid socket error
}

server.sin_family = AF_INET;
server.sin_addr.s_addr= INADDR_ANY;
server.sin_port = htons (PORT);

if (bind(s, (stuct sockaddr* ) &server, sizeof(server)) == SOCKET_ERROR)
{
  //bind error
}

OVERLAPPED ovWrite;
memset(&ovWrite,0,sizeof(ovWrite));
ovWrite.offset=0;
ovWrite.OffsetHigh=0;
ovWrite.hEvent = CreateEvent (0,TRUE,0,0);

memset(buf,'\0',BUFLEN);


while (1) 
{
  if (!recvfrom(s, buf, BUFLEN,0,(struct sockaddr *) &client_address, &client_length)
  {
    fprintf(stderr, "Recvfrom Failed %d\n", WSAGetlastError());
  }

  if (!WriteFileEx(serialHandle, buf, strlen(buf),&ovWrite,NULL))
  {
     fprintf(stderr, "Error writing to COM port %d\n", GetlastError());
  }
   memset(buf,'\0', BUFLEN);
}

我正在使用lcc编译器,结果程序在循环的第二次迭代中崩溃,访问冲突为0xc0000005。当我用另一个输入源(如stdin )替换recvfrom时,程序运行正常。这是一个已知的问题,还是两个函数调用不能共存?

EN

回答 2

Stack Overflow用户

发布于 2013-08-09 18:16:34

recvfrom()不会将'\0'添加到buf,因此至少()如果recvfrom()读取BUFLEN字节,或者在第一次调用时,如果buf没有在代码片段外部初始化,则调用strlen()会导致UB。此外,您的if( recvfrom( ... ) )是错误的,因为在成功的情况下,` `recvfrom()返回接收到的字节数,因此条件为真。相反,您可以这样做:

代码语言:javascript
复制
size_t received;

....

if ((received = recvfrom(s, buf, BUFLEN,0,(struct sockaddr *) &client_addres, &client_length)) <= 0 )
{
     fprintf(stderr, "Recvfrom Failed %d\n", WSAGetlastError());
}

if (!WriteFileEx(serialHandle, buf, received,&ovWrite,NULL))
{
     fprintf(stderr, "Error writing to COM port %d\n", GetlastError());
}
票数 0
EN

Stack Overflow用户

发布于 2013-08-09 20:03:22

好的,我将提升自己来提供答案:)一些要点:

1)与WASRecv不同的是,WriteFileEx()总是需要一个有效的完成例程来回调异步写调用的完成。其他信令机制,如使用hEvent同步,不适用于此呼叫。传递NULL可能会导致AV。

2)一般情况下,UDP报文可以是任意长度0..64K。recvFrom()返回这类消息的实际长度,应该使用这个值来处理它-而不是任何BUFFER_LEN或strlen()调用(参见Ingo answer:)。

3) IP堆栈可以同时处理来自一个线程的阻塞读操作和来自另一个线程的写操作-不一定要求助于异步、重叠的I/O。

4)如果要使用重叠I/O,强烈建议对每个调用使用不同的OVL块和缓冲区-通常,多个重叠的操作可以同时排队,并且每个操作都必须有自己的缓冲区/OVL。我为每个调用使用错误定位的结构(或者,如果是C++,则是新的类实例),或者从池中分配的*结构,以确保这一点。结构/实例可以在处理之后在完成例程中馈送/删除/重新汇集(或者在线程之外排队,然后在其他地方处理/释放/删除/重新汇集)。

5)希望使用完成例程执行重叠I/O的线程应该看起来像是围绕其中一个可警报等待调用的循环。WaitForSingleObjectEx()很方便,因为它可以以可警示的方式等待一个信号量,该信号量构成生产者-消费者队列的基础,允许其他线程向执行重叠I/O的线程发送命令/缓冲区/任何东西。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18144171

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档