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

为了理解第二人生的客户端与服务器的沟通,那么下面就来分析一下第二人生采用的网络协议。在目前的网络里,主要有两个协议: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 深圳
 
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值