关于游戏开发:游戏开发网络篇-Net框架

前言:本篇文章主题Tcp连贯Socket套接字相干内容,对根底局部、优化补充局部做了阐明,最终目标是让阅读者看完本篇文章后能写一个功能完善的网络框架。

首先明确一下网络连接的根底模块有哪些

[根底局部2]数据接管

客户端Socket连贯后开始接收数据,客户端接收数据的形式个别有两种

[数据接管第一种]
开线程,为何开线程:数据接管不须要和Mono交互,仅仅是对byte[]数据的操作,开线程提高效率,上面是代码示例
这个没什么好说的,四个重载接口区别不大

//数据初始化
uint ReceiveMaxByteCount;
byte[] bufferTemp = new byte[ReceiveMaxByteCount];
 
pubvoid void Connect(string _ip,int _port)
{
     SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream,    
                           ProtocolType.Tcp);
    IPAddress ip = IPAddress.Parse(_ip);
    IPEndPoint point = new IPEndPoint(ip, _port);
    SocketClient.NoDelay = true;
    SocketClient.Connect(point);   
}

[根底局部2]数据接管

客户端Socket连贯后开始接收数据,客户端接收数据的形式个别有两种

[数据接管第一种]

开线程,为何开线程:数据接管不须要和Mono交互,仅仅是对byte[]数据的操作,开线程提高效率,上面是代码示例

pubvoid void Connect(string _ip,int _port)
{
     SocketClient = new Socket()
    //...........
    //这是第一种形式,开线程接管
    Thread c_thread = new Thread(Received);
    c_thread.IsBackground = true;
    c_thread.Start();
}
void Received()
{
    while (true)
    {
        try
        {
            int len = _SocketClient.Receive(bufferTemp);   //len 理论接管到的无效字节数
            if (len <= 0)
            {
                //异样解决
                break;
            }
            //把收到的字节解析或者塞入接管缓存池中
        }
        catch { }
    }
}

[数据接管第二种]

简略粗犷的写在Update里,如果是框架则应该有tick 接管和发送缓存池的机制,这里是根底局部,只介绍外围代码

void Update()
{
    ProcessReceive()
}
 
void ProcessReceive()
{
    uint recLen = 0;
    if( client.Connected)
    //maxLen代表最大接管长度,如果有缓存池,接管长度不能超过缓存池残余量的长度
    recLen = (uint)client.Receive(bufferTemp,maxLen, SocketFlags.None);
    //有池则入池,没池间接解析bufferTemp,数据长度为recLen
}

[根底局部3]数据发送

void Send (Socket client, Byte[] buff, uint nLen, SocketFlags flags = SocketFlags.None)
{
    try
    {
        //提醒:sendLen代表向tcp底层缓冲区塞了多少个字节,并不是向服务器发送胜利了多少个字节
        uint sendLen = client.Send(buff, (int)nLen, flags);
    }
    catch (SocketException e)
    {
    }
    
}

[根底局部4]:断开连接

void Close (Socket ClientSocket)
{
    try
    {
        ClientSocket.Shutdown(SocketShutdown.Both);
        ClientSocket.Close();
        
    }
    catch (SocketException e)
    {
        //LogSystem.Error(e.ToString());
    }
}

Socket根底局部外的优化

[补充优化1]发送、接管缓存池

咱们能够把发送缓存池和接管缓存池都封装成一个class,未来数据发送和接管的重任就落到了它俩身上,输入叫SocketOutputPool,输出叫SocketInputPool

[补充优化1-发送缓存池]

发送缓存池是干嘛的?基本原理就是保护一个Byte数组。

当下层业务有数据向服务器发送时,会调用NetMgr的send函数,send函数再调用SocketOutputPool的Write函数向Byte数组中写入该数据。

缓存池的数据适合发送,发送多少?当Write函数写入数据后,该当记录一下以后数据长度,int变量m_PoolTail记录尾部长度,上文有过对发送机会的形容,一般来说会在Update中调用发送函数

public const uint DEFAULT_SOCKET_OUTPUT_BUFFER_SIZE = 1024 * 80;//缓存最大长度
int m_Tail = 0; //缓存池以后长度
byte[] m_Buffer = new Byte[DEFAULT_SOCKET_OUTPUT_BUFFER_SIZE];
 
void TickSend()
{
    //再次提醒:SendLen不是向服务器发送的长度,而是往Tcp发送缓冲区塞了多少数据
    int SendLen = Socket.Send(m_Buffer,m_PoolTail, flag);
    
    //发送完结后,须要从池中把发送过得数据剔除
}

3、数据发送和数据接管能够写两个缓存池

 

注意事项:

1、Tcp是否须要缓存池,可设置bool变量Nodelay

2:socket.Send()办法的返回变量int值示意该send向tcp发送缓冲区塞了多少个字节,并不是向服务器发送胜利了多少个字节,

3:如果呈现发包失败,tcp底层会主动重发,tcp的底层有发送胜利回复机制,另一端收到音讯包后会回复一个确认包
图片起源:http://www.pizei.com/ 页游

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理