使用C# SocketTCP开发网络游戏ForestWars(二) 创建服务端与客户端并实现消息的同步以及异步发送与接收

本章主要讲述如何使用VS控制台程序创建服务器,使用Unity创建客户端,然后实现消息的同步以及异步接收与发送。

一 同步与异步的区别

简单来说,同步就是进行一种操作,在操作没结束前不能进行其它操作。这就好比与记录10个学生跑400米需要多少时间,让一个学生起跑后,必须等到他跑完才能让下一个同学起跑。而异步则是在进行某种操作后,可以继续进行下一个操作,也就是在让一个同学起跑后再让下一个同学起跑。异步与同步相比,效率高,但是管理复杂。

二 服务端业务逻辑

用VS新建C#控制台项目TCP_Sever,添加Sever类。

Sever.cs

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

namespace TCP_Sever
{
    class Sever
    {
        /// <summary>
        /// 服务器套接字
        /// </summary>
        private static Socket sever_socket;
        /// <summary>
        /// 最大连接数
        /// </summary>
        private static int maxConn = 50;
        /// <summary>
        /// 数据缓存池
        /// </summary>
        private static byte[] readBuff = new byte[1024];
        /// <summary>
        /// 开启服务器
        /// </summary>
        /// <param name="host">IP地址</param>
        /// <param name="port">端口号</param>
        public static void Start(string IP, int port)
        {
            //创建服务器套接字
            sever_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绑定IP和端口号
            IPAddress ip = IPAddress.Parse(IP);
            IPEndPoint point = new IPEndPoint(ip, port);
            sever_socket.Bind(point);
            //监听,0无限制
            sever_socket.Listen(maxConn);
            Console.WriteLine("服务器开启成功");
        }
        /// <summary>
        /// 同步接收与发送
        /// </summary>
        public static void SynRecv_Send()
        {
            //客户端接入
            if (sever_socket == null)
            {
                Console.WriteLine("请先开启服务器");
                return;
            }
            Socket connfd = sever_socket.Accept();
            Console.WriteLine("客户端接入");
            //获取接收到的流转换为字符串
            int count;
            try
            {
               count= connfd.Receive(readBuff);
            }
            catch (Exception e)
            {
                Console.WriteLine("客户端异常"+e.Message);
                return;
            }
            string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
            Console.WriteLine("收到信息:" + str);
            //获取输入,发送给客户端
            str="服务器接收到消息:"+str;
            byte[] writeBuff = System.Text.Encoding.UTF8.GetBytes(str);
            connfd.Send(writeBuff);
            connfd.Close();
        }
        
        /// <summary>
        /// 异步接收
        /// </summary>
        public static void AsynRec()
        {
            //客户端接入
            if (sever_socket == null)
            {
                Console.WriteLine("请先开启服务器");
                return;
            }
            Socket connfd = sever_socket.Accept();
            Console.WriteLine("客户端接入");
            //异步接收
            try
            {
                connfd.BeginReceive(readBuff, 0, 1024, SocketFlags.None,AsynReceiveCallBack, connfd);
            }
            catch (Exception e)
            {
                Console.WriteLine("客户端异常"+e.Message);
                return;
            }
        }
        /// <summary>
        /// 异步接收回调
        /// </summary>
        /// <param name="ar"></param>
        private static void AsynReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                //获得客户端套接字
                Socket clientSocket = ar.AsyncState as Socket;
                int count = clientSocket.EndReceive(ar);
                string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
                Console.WriteLine("接收到消息:" + str);
                AsynSend(clientSocket);
                //继续接收,实现循环
                clientSocket.BeginReceive(readBuff, 0, 1024, SocketFlags.None, AsynReceiveCallBack, clientSocket);
            }
            catch (Exception e)
            {
                Console.WriteLine("客户端断开:" + e.Message);
            }
           
        }
        /// <summary>
        /// 异步发送
        /// </summary>
        public static void AsynSend(Socket clientsocket)
        {
            //客户端接入
            if (sever_socket == null)
            {
                Console.WriteLine("请先开启服务器");
                return;
            }
            byte[] writerBuff = System.Text.Encoding.UTF8.GetBytes("客户端你好");
            try
            {   
                //异步发送
                clientsocket.BeginSend(writerBuff, 0, writerBuff.Length, SocketFlags.None, null, null);
            }
            catch (Exception e)
            {
                Console.WriteLine("发送消息失败" + e.Message);
            }
        }
    }

}

Program.cs

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

namespace TCP_Sever
{
    class Program
    {
        static void Main(string[] args)
        {
            Sever.Start("127.0.0.1", 6688);
            while (true)
            {
                //同步
                //Sever.SynRecv_Send();
                //异步
                Sever.AsynRec();
            }
        }
    }
}

三 客户端端业务逻辑

打开Unity,新建Client和Manager类。将Manager挂载在场景的空物体上。

Client.cs

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

namespace YCX_Tool.Client
{
    public class Client
    {
        /// <summary>
        /// 客户端套接字
        /// </summary>
        private static Socket client_socket;
        /// <summary>
        /// 数据缓存池
        /// </summary>
        private static byte[] readBuff = new byte[1024];
        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="IP"></param>
        /// <param name="Port"></param>
        public static void Start(string IP, int Port)
        {
            //创建客户端套接字
            client_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //连接
            try
            {
                client_socket.Connect(IP, Port);
                Debug.Log("服务端连接");
            }
            catch (System.Exception e)
            {

                Debug.Log(e.Message);
            }    
        }
        /// <summary>
        /// 同步接收与发送
        /// </summary>
        public static void SynRecv_Send()
        {
            if (client_socket == null)
            {
                Debug.Log("请先开启客户端");
                return;
            }
            //发送
            string str = "Hello Unity";
            byte[] writeBuff = System.Text.Encoding.UTF8.GetBytes(str);
            client_socket.Send(writeBuff);
            //接收
            try
            {
                int count = client_socket.Receive(readBuff);
                str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
                Debug.Log("接收到消息:" + str);
            }
            catch (System.Exception e)
            {
                Debug.Log("接收异常" + e.Message);
            }
                 
        }
        /// <summary>
        /// 异步接收
        /// </summary>
        public static void AsynRec()
        {
            //客户端接入
            if (client_socket == null)
            {
                Debug.Log("请先开启服务器");
                return;
            }
            //异步接收
            try
            {
                client_socket.BeginReceive(readBuff, 0, 1024, SocketFlags.None, AsynReceiveCallBack, null);
            }
            catch (Exception e)
            {
                Debug.Log("客户端异常" + e.Message);
                return;
            }
        }
        /// <summary>
        /// 异步接收回调
        /// </summary>
        /// <param name="ar"></param>
        private static void AsynReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                //获得客户端套接字
                int count = client_socket.EndReceive(ar);
                string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
                Debug.Log("接收到消息:" + str);
                //继续接收,实现循环
                client_socket.BeginReceive(readBuff, 0, 1024, SocketFlags.None, AsynReceiveCallBack, null);
            }
            catch (Exception e)
            {
                Debug.Log("服务器断开:" + e.Message);
            }
            
        }
        /// <summary>
        /// 异步发送
        /// </summary>
        public static void AsynSend()
        {
            //客户端接入
            if (client_socket == null)
            {
                Debug.Log("请先开启服务器");
                return;
            }
            byte[] writerBuff = System.Text.Encoding.UTF8.GetBytes("服务端你好");
            try
            {
                //异步发送
                client_socket.BeginSend(writerBuff, 0, writerBuff.Length, SocketFlags.None, null, null);
            }
            catch (Exception e)
            {
               Debug.Log("发送消息失败" + e.Message);
            }
        }
    }
}

Manager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YCX_Tool.Client;

public class Manager : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Client.Start("127.0.0.1", 6688);
        Client.AsynRec();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            Client.AsynSend();
        }
    }
}

四 调试

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值