Unity网络开发记录(三):封装服务端的相关socket

15 篇文章 0 订阅

客户端与服务端通讯socket

封装此类,是为了方便维护客户端和服务端建立连接后返回的socket

包含了所需要的基础的socket 以及 该socket所对应的id号,方便进行管理

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

namespace TechTcpServerTest2
{
    internal class ClientTcpSockt
    {
        private static int CLIENT_NUMBER = 0;
        public int clientID = 0;
        private Socket? socket;

        public ClientTcpSockt(Socket _socket)
        {
            socket = _socket;
            clientID = CLIENT_NUMBER;
            ++CLIENT_NUMBER;
        }

        public void Send(string info)
        {
            if (socket != null)
            {
                try
                {
                    socket.Send(Encoding.UTF8.GetBytes(info));
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);   
                }
            }
        }

        public void Receive()
        {
            if (socket != null)
            {
                try
                {
                    if (socket.Available > 0)
                    {
                        byte[] buffer = new byte[1024 * 5];
                        int num = socket.Receive(buffer);
                        ThreadPool.QueueUserWorkItem(HandleMsg, Encoding.UTF8.GetString(buffer, 0, num));
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }

        private void HandleMsg(object obj)
        {
            string info = (string)obj;
            if (socket != null)
            {
                Console.WriteLine("{0}客户端,信息:{1}", socket.RemoteEndPoint, info);
            }
        }

        public void Close()
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
                socket = null;
            }
        }
    }
}

服务端socket

此类具有基础的socket 以及 一个客户端类的字典,按照 特定的id与socket进行对应

对于客户端的连接请求以及消息的接收处理依旧采用多线程去处理

对于accept一直循环去监听,如果有新连接就加入到字典当中

对于receive,就一直循环的调用字典中存储对象的receive方法

关闭对客户端的连接,只需要循环调用字典内 刚刚封装的客户端-服务端socket对象中的关闭方法就行

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

namespace TechTcpServerTest2
{
    internal class ServerTcpSocket
    {
        private Socket socket;
        private Dictionary<int, ClientTcpSockt> clientDic = new Dictionary<int, ClientTcpSockt>();
        private bool isConnected;
        public bool IsConnected => isConnected;

        public void Start(string ip, int port, int num)
        {
            isConnected = false;
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);
            socket.Bind(ipPoint);
            socket.Listen(num);

            ThreadPool.QueueUserWorkItem(Accept);
            ThreadPool.QueueUserWorkItem(Receive);
        }

        public void Accept(object obj)
        {
            while (!isConnected)
            {
                try
                {
                    Socket client = socket.Accept();
                    ClientTcpSockt clientTcpSockt = new ClientTcpSockt(client);
                    clientDic.Add(clientTcpSockt.clientID, clientTcpSockt);
                    clientTcpSockt.Send("服务器连接成功");
                }
                catch (Exception e)
                {
                    Console.WriteLine("客户端连接出错 " + e.Message);
                }
            }
        }

        public void Receive(object obj)
        {
            while (!isConnected)
            {
                try
                {
                    if (clientDic.Count > 0)
                    {
                        foreach (var item in clientDic.Values)
                        {
                            item.Receive();
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("客户端接收出错 " + e.Message);
                }
            }
        }

        public void Close()
        {
            foreach(var item in clientDic.Values)
            {
                item.Close();
            }
            clientDic.Clear();

            isConnected = true;
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
        }

        public void Broadcast(string info)
        {
            if (socket != null)
            {
                foreach (var item in clientDic.Values)
                {
                    item.Send(info);
                }
            }
        }
    }
}

启动

开始先初始化一个与服务相关的socket类对象,调用前面所写的start方法初始化绑定ip地址、端口号、监听大小

然后该类对象会自动进行处理相应的客户端连接,以及相关的通讯工作。对于客户端,最基本的代码connect就可以连接该服务器并进行通讯

namespace TechTcpServerTest2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ServerTcpSocket socket = new ServerTcpSocket();
            socket.Start("127.0.0.1", 8080, 1024);
            Console.WriteLine("服务器开启");
            while(true)
            {
                string input = Console.ReadLine();
                if (input == "Quit")
                {
                    socket.Close();
                }
                else if (input.Substring(0, 2) == "B:")
                {
                    socket.Broadcast(input.Substring(2));
                }
            }
        }
    }
}

启动客户端和该新的服务端后,可以发现依然能够正常连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值