我用UDP做了一个c/s结构的通信程序,client启动后会向server发送一个请求,而server启动后也会向每个记录的client发送一个请求,当server和client在同一台机器上时,server端发送给client端(实际是自己的地址)请求后,server自己会收到该请求,并报错:recvfrom error 10054。(但实际上server 在sendto时,指定的是client的port,而非server的port)。奇怪的是,client端类似的操作,启动后发送请求给本机的server,但client端就不会收到该请求,不会报错!
当然,将server和client放到两台不同的机器上,肯定没有问题!
请教各位大虾!:)

解决方案 »

  1.   

    udp接收的端口绑定的时候,server和client是不是同时绑定到一个窗口句柄上去了?
      

  2.   

    younggle,端口肯定是没有问题!:(
    howtotell,你是指WSAAsyncSelect的吧,的确都是用this->m_hWnd。难道和它有关系吗?
      

  3.   

    重新测试了一下,此问题改为:
    一个c/s结构的UDP通信程序,实际上client和server的socket部分代码几乎相同(除了各自绑定的端口号不同)。1.建立socket;s = socket (PF_INET, SOCK_DGRAM, 0);
    2.WSAAsyncSelect(s,this->m_hWnd, WM_LISTEN_MESSAGE, FD_READ);
    3.绑定;bind(s,...);
    4.在自定义的消息函数OnReceivedData(WPARAM wParam, LPARAM lParam)中处理接收到的信息。client启动后会向server发送一个请求,而server启动后也会向每个client发送一个请求,问题是:server端发出请求后,自己会收到该请求,报错:recvfrom error 10054(WSAECONNRESET)
    奇怪的是,client端类似的操作,启动后发送请求给server,但client端就不会收到该请求,不会报错!
    注:client是基于对话框的程序,server是基于单文档的程序!
      

  4.   

    你的client处于内网中,而server处于公网中吧?
    通过udp发送数据时,如果目的地址有误或者无法到达,就有可能收到10054错误。内网中的机器的ip是类似于192.168.*.*这样的虚拟ip,公网上的机器直接往这样的地址上发送数据,当然出错了。
      

  5.   

    搞定啦!多谢大家!方法如下:1.头文件中加入下面代码:
    #include <Winsock2.h>
    #pragma comment(lib,"ws2_32.lib")
    #define IOC_VENDOR 0x18000000
    #define _WSAIOW(x,y) (IOC_IN|(x)|(y))
    #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)2.在创建socket之后加入下面代码:
    DWORD dwBytesReturned = 0;
    BOOL  bNewBehavior = FALSE;
    DWORD status;status = WSAIoctl(m_hSock, SIO_UDP_CONNRESET,
                      &bNewBehavior,
                      sizeof (bNewBehavior),
                      NULL, 0, &dwBytesReturned,
                      NULL, NULL);具体原理参见下面这篇MSDN的文章
      

  6.   

    Knowledge Base Articles   WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out
    Q263823
    --------------------------------------------------------------------------------
    The information in this article applies to:Microsoft Windows 2000 Professional 
    Microsoft Windows 2000 Server 
    Microsoft Windows 2000 Advanced Server--------------------------------------------------------------------------------
    SYMPTOMS
    In Windows 2000, a User Datagram Protocol (UDP) program may not work and may generate a WSAECONNRESET response. CAUSE
    If sending a datagram using the sendto function results in an "ICMP port unreachable" response and the select function is set for readfds, the program returns 1 and the subsequent call to the recvfrom function does not work with a WSAECONNRESET (10054) error response. In Microsoft Windows NT 4.0, this situation causes the select function to block or time out. RESOLUTION
    To resolve this problem, obtain the latest service pack for Windows 2000. For additional information, please see the following article in the Microsoft Knowledge Base: Q260910 How to Obtain the Latest Windows 2000 Service Pack 
    A new sockets IOCTL called "SIO_UDP_CONNRESET" has been introduced in Windows 2000. When this IOCTL is used, the program must be rewritten specifically for Windows 2000 to obtain the original Windows NT 4.0 behavior. Windows NT 4.0, Microsoft Windows 95, and Microsoft Windows 98 have no support for this new IOCTL. In addition to rewriting your application, you will need the hotfix referenced further down in this article. The following code snippet demonstrates a technique that can be used to call WSAIoctl with the SIO_UDP_CONNRESET control code to obtain the original Windows NT 4.0 behavior: DWORDdwBytesReturned = 0;
    BOOLbNewBehavior = FALSE;
    DWORDstatus;// disable  new behavior using
    // IOCTL: SIO_UDP_CONNRESET
    status = WSAIoctl(sd, SIO_UDP_CONNRESET,
    &bNewBehavior, sizeof(bNewBehavior),
                       NULL, 0, &dwBytesReturned,
                       NULL, NULL);if (SOCKET_ERROR == status)
    {
    DWORD dwErr = WSAGetLastError();
    if (WSAEWOULDBLOCK == dwErr)
    {
    // nothing to do
    return(FALSE);
    }
    else
    {
    printf("WSAIoctl(SIO_UDP_CONNRESET) Error: %d\n", dwErr);
    return(FALSE);
    }

    To be able to compile this code, you need either to have the latest Mswsock.h which includes the definition of SIO_UDP_CONNRESET or to insert below definition of it directly into your code: // MS Transport Provider IOCTL to control
    // reporting PORT_UNREACHABLE messages
    // on UDP sockets via recv/WSARecv/etc.
    // Path TRUE in input buffer to enable (default if supported),
    // FALSE to disable.
    #defineSIO_UDP_CONNRESET_WSAIOW(IOC_VENDOR,12) 
    NOTE: The hotfix that is described in this article will not resolve the problem unless the program is rewritten to use the new SIO_UDP_CONNRESET IOCTL.In order to compile this code, it is necessary to have the latest Platform SDK installed on your computer. This is available from the following MSDN Web site:
    http:\\msdn.microsoft.com
    For additional information, click the article number below to view the article in the Microsoft Knowledge Base:
    Q263823 WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out STATUS
    Microsoft has confirmed this to be a problem in the Microsoft products that are listed at the beginning of this article. This problem was first corrected in Windows 2000 Service Pack 2.MORE INFORMATION
    For additional information about how to install Windows 2000 and Windows 2000 hotfixes at the same time, click the article number below to view the article in the Microsoft Knowledge Base:Q249149 Installing Microsoft Windows 2000 and Windows 2000 Hotfixes Additional query words: Keywords : kbWin2000PreSP2Fix kbWin2000SP2Fix 
    Issue type : kbbug 
    Technology : kbwin2000AdvServ kbwin2000AdvServSearch kbwin2000Serv kbwin2000ServSearch kbwin2000Search kbwin2000ProSearch kbwin2000Pro kbWinAdvServSearch