服务器和客户端注释版

服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using Player;

namespace NBkalasi
{
    internal class Client
    {
        public Socket socket;//定义个套接字
        public string ipads;//IP地址
        public byte[] data = new byte[1024];//数据的容量
        public byte[] stream = new byte[0];//流

      //  public Player player;   
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace NBkalasi
{
    internal class NetManager : Singleton<NetManager>
    {
        Socket socket;
        //存所有客户端的集合
        public List<Client> clientlist = new List<Client>();
        public void Init()
        {
            //socket 赋值
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //给socket进行绑定
            socket.Bind(new IPEndPoint(IPAddress.Any, 33333));//33333为你的端口号
            //可以监听的上限为  10个
            socket.Listen(10);
            //开始接受客户端发送来的链接  1 当有客户端发送链接请求就调用函数
            socket.BeginAccept(Linkq, null);
            Console.WriteLine("启动服务器");
        }
        //客户端链接 调用
        private void Linkq(IAsyncResult ar)
        {

            Client client = new Client();
            //异步需要把ar结束后 赋给socket
            client.socket = socket.EndAccept(ar);
            //把ar传过来的ip和端口 接一下
            IPEndPoint ipend= client.socket.RemoteEndPoint as IPEndPoint;
            //拼接客户端的ip+端口
            client.ipads = ipend.Address+":"+ipend.Port;
            //输出一下 添加到集合
            Console.WriteLine(client.ipads+"连接了");
            clientlist.Add(client);

            //这个客户端开始接受数据 1.byte[] 数组,2.从第0位开始接受3.数组总长度4.传输的协议为none 5.接受数据的回调函数 6.自己
            client.socket.BeginReceive(client.data,0,client.data.Length,SocketFlags.None,OnReceive,client);
            //再次接收链接
            socket.BeginAccept(Linkq, null);

        }

        private void OnReceive(IAsyncResult ar)
        {
            try
            {
                //服务器获取已经链接的客户端
                Client client = ar.AsyncState as Client;
                //服务器获取已经链接的客户端的数据长度
                int len = client.socket.EndReceive(ar);
                //判读是否有数据
                if (len>0)
                {
                    //有数据的话 建立一个缓存全部数据的容器
                    byte[] Allbyte = new byte[len];
                    //把该客户端的缓存数据复制到容器里,把数组的第0位 copy 到 allbyte 的第0位开始 ,copy的长度
                    Buffer.BlockCopy(client.data,0,Allbyte,0,Allbyte.Length);
                    // 把缓存好的数据进行拼接拼接给最后的实际数据  把allbyte 拼接到流里   
                    client.stream = client.stream.Concat(Allbyte).ToArray();
                    // 长度(包头加包体 2字节) +包头(id  int 4字节) + 包体(数据)==包
                    while (client.stream.Length>=2)
                    {
                        //获取包头和包体的长度(api的意思是从数据的第0位开始,获取Ushout类型的数据 获取到就结束)
                        ushort onelen =BitConverter.ToUInt16(client.stream,0);
                        //获取包里面数据的 总长度
                        int alllen = 2 + onelen;
                        //判断是否有一个以上的包
                        if (client.stream.Length >= alllen)
                        {
                            //建立一个只存包头+包体的缓存数据的容器
                            byte[] onedata = new byte[onelen];
                            //从该客户端的数据里,去除包里长度后(长度是2字节,也就是从包头开始Copy数据),
                            Buffer.BlockCopy(client.stream, 2, onedata, 0,onedata.Length);
                            //从上面的容器里 第0位开始获取id;
                            int id = BitConverter.ToInt32(onedata,0);
                           // Console.WriteLine(id);
                           //从上面容器 除去id(包头)的字节数  创建包体的容器
                            byte[] onedata2 = new byte[onedata.Length-4];
                            //从上面包头加包体的容器里除去包头  copy 包体到上面包体的容器里
                            Buffer.BlockCopy(onedata, 4, onedata2, 0, onedata2.Length);
                            //消息中心发送(id消息号,包体作为数据,传过来的客户端)
                            MessageCenter.Ins.OnDisPatch(id, onedata2,client);

                            //看看数据里是否有剩余的包
                            int sylen = client.stream.Length - alllen;
                            //如果有
                            if (sylen>0)
                            {
                                //创建个存储的容器
                                byte[] sybyte = new byte[sylen];
                                //把剩余的数据copy 到剩余包的容器中
                                Buffer.BlockCopy(client.stream, alllen, sybyte, 0,sybyte.Length);
                                //重新给数据赋值
                                client.stream = sybyte;
                            }
                            else
                            {
                                //如果没有剩余的包 给他变成空的数组
                                client.stream = new byte[0];
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    //只要客户端传数据 都会重新调用方法
                    client.socket.BeginReceive(client.data, 0, client.data.Length, SocketFlags.None, OnReceive, client);
                }
                else
                {
                    //如果没有数据 都关闭
                    client.socket.Shutdown (SocketShutdown.Both);
                    client.socket.Close();
                    clientlist.Remove(client);
                    Console.WriteLine(client.ipads+"滚啦");
                }
            }
            catch (Exception ex)
            {

                Console.WriteLine(ex);
            }
        }

        public void Send(int id,byte[] body,Client client)
        {
            byte[] head = BitConverter.GetBytes(id);
            byte[] upbody = BitConverter.GetBytes((ushort)(head.Length + body.Length));
            byte[] allbody = new byte[0];
            allbody = allbody.Concat(upbody).ToArray();
            allbody = allbody.Concat(head).ToArray();
            allbody = allbody.Concat(body).ToArray();
            client.socket.BeginSend(allbody, 0, allbody.Length, SocketFlags.None, OnSend, client);
        }

        private void OnSend(IAsyncResult ar)
        {
            Client client = (Client)ar.AsyncState;
            int len = client.socket.EndSend(ar);
            Console.WriteLine("发送长度"+len);
        }

        public void OnAllSend(int id,byte[] body)
        {
            for (int i = 0; i < clientlist.Count; i++)
            {
                Send(id, body, clientlist[i]);
            }
        }
    }
}

客户端

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Linq;
using System;

public class NetManager : Singleton<NetManager>
{
    Socket socket;
    public byte[] data = new byte[1024];
    public byte[] stream = new byte[0];
    Queue<byte[]> queue = new Queue<byte[]>();
    public void Init()
    {
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
       
        socket.BeginConnect("127.0.0.1",33333,OnConnect, null);
        
    }

    private void OnConnect(IAsyncResult ar)
    {
       
         socket.EndConnect(ar);
     
       
        socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
        
    }

    private void OnReceive(IAsyncResult ar)
    {
        try
        {
          
            int len = socket.EndReceive(ar);
            if (len > 0)
            {
                byte[] alldata = new byte[len];
                Buffer.BlockCopy(data, 0, alldata, 0, len);
                stream = stream.Concat(alldata).ToArray();
                while (stream.Length >= 2)
                {
                    ushort baolen = BitConverter.ToUInt16(stream, 0);
                    int alllen = 2 + baolen;
                    if (stream.Length >= alllen)
                    {
                        byte[] idbody = new byte[baolen];
                        Buffer.BlockCopy(stream, 2, idbody, 0, baolen);
                        queue.Enqueue(idbody);
                       

                        int sylen = stream.Length - alllen;
                        if (sylen > 0)
                        {
                            byte[] sydata = new byte[sylen];
                            Buffer.BlockCopy(stream, alllen, sydata, 0, sylen);
                            stream = sydata;
                        }
                        else
                        {
                            stream = new byte[0];
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }

                }
                socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
            }
            else
            {
               
              
            }
        }
        catch (Exception ex)
        {

            Console.WriteLine(ex);
        }
    }
    public void Send(int id, byte[] body)
    {
        byte[] head = BitConverter.GetBytes(id);
        byte[] len = BitConverter.GetBytes((ushort)(head.Length + body.Length));
        byte[] alldata = new byte[0];
        alldata = alldata.Concat(len).ToArray();
        alldata = alldata.Concat(head).ToArray();
        alldata = alldata.Concat(body).ToArray();
        if (socket.Connected)
        {
            socket.BeginSend(alldata, 0, alldata.Length, SocketFlags.None, OnSend, null);
        }

    }

    private void OnSend(IAsyncResult ar)
    {
      
        int len = socket.EndSend(ar);
        Console.WriteLine("发送的长度为" + len);
    }

    public void Close()
    {
        socket.Shutdown(SocketShutdown.Both);
        socket.Close();
    }

    public void UpData()
    {
        if (queue.Count>0)
        {
            byte[] idbody = queue.Dequeue();
            int id = BitConverter.ToInt32(idbody, 0);
            byte[] body = new byte[idbody.Length - 4];
            Buffer.BlockCopy(idbody, 4, body, 0, idbody.Length - 4);
            MessageCenter.Ins.OnDisPatch(id, body);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值