第二人生的源码分析 二十六 底层网络协议

               
为了理解第二人生的客户端与服务器的沟通,那么下面就来分析一下第二人生采用的网络协议。在目前的网络里,主要有两个协议:TCP和UDP,而第二人生里是采用UDP协议。TCP协议与UDP协议的主要区别,就是TCP有流量控制,可靠性控制,IP层组包功能,连接需要三次握手,而UDP没有这些保证,因此UDP发送的数据包需要自己来管理数据的有序性和可靠性。先来分析最底层的协议,它调用UDP发送数据的源码如下:
#001 // Returns TRUE on success.
#002 BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort)
#003 {
#004       // Sends a packet to the address set in initNet
#005       // 
#006       int nRet = 0;
#007       U32 last_error = 0;
#008 
#009       stDstAddr.sin_addr.s_addr = recipient;
#010       stDstAddr.sin_port = htons(nPort);
#011       do
#012       {
#013              nRet = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));                
#014      
#015 
#016              if (nRet == SOCKET_ERROR )
#017              {
#018                     last_error = WSAGetLastError();
#019                     if (last_error != WSAEWOULDBLOCK)
#020                     {
#021                            // WSAECONNRESET - I think this is caused by an ICMP "connection refused"
#022                            // message being sent back from a Linux box... I'm not finding helpful
#023                            // documentation or web pages on this. The question is whether the packet
#024                            // actually got sent or not. Based on the structure of this code, I would
#025                            // assume it is. JNC 2002.01.18
#026                            if (WSAECONNRESET == WSAGetLastError())
#027                            {
#028                                   return TRUE;
#029                            }
#030                            llinfos << "sendto() failed to " << u32_to_ip_string(recipient) << ":" << nPort
#031                                   << ", Error " << last_error << llendl;
#032                     }
#033              }
#034       } while ( (nRet == SOCKET_ERROR)
#035                      &&(last_error == WSAEWOULDBLOCK));
#036 
#037       return (nRet != SOCKET_ERROR);
#038 }
 
在13行里调用WINDOWS API函数sendto来发送数据sendBuffer到目标地址stDstAddr里,这样就可以把数据交给WINDOWS的网络去发送数据了。由于这里采用异步的UDP来发送数据,因此采用了一个do while来处理正在阻塞的情况。当发送不成功,并且错误码是WSAEWOULDBLOCK,说明WINDOWS API正在发送过程中,不能接收数据,这样就循环地检查,直到发送成功,或者出错为止。第二人生里跟服务器发送的消息,就是这样发送出去的,看起来比较简单吧。
  蔡军生  2008/3/20 QQ:9073204 深圳
            

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/uytrrfg/article/details/87621888