基于Socket通信的小实例

距离上次更博已经好长的时间了,上班了工作了,确实空闲下来的时间少了,然而我更多的在思考在于,写些啥,有啥东西是可以放进博客里的,千篇一律的教程亦或是自己研究出来的东西,我想更应该是后者吧,不然我这博客也是搭得没意思。

话不多说,今天我们来了解下Socket相关的知识,可以说的上是基础,做了点小通信(其实也简单啦)~

实现效果

先说整个实例在实现效果上,由于本实例只是对Socket相关的使用做了个基本的测试,所以在效果上确实是差强人意,也就不上图了,大体的效果描述就是:在Unity搭建的客户端,创建的UI按钮上进行点击,给服务端进行消息的发送,而后服务端返回相应的消息,不同的消息发送有不同的回应而已。

效果不重要,毕竟才基础,里面的原理才是我们需要了解的~

服务端搭建

这里的服务端,博主采取的是通过VS创建控制台程序,在电脑上开启服务端代码,主程序入口如下

Program.cs

 using System;
    class Program
        {
            static void Main(string[] args)
            {
                Server server = new Server("127.0.0.1",8899);
                server.Start();
    
                Console.ReadKey();
            }
        }

其实主程序无非就是创建了服务类,开启服务而已,而这里的服务类就是Socket相关使用的主体了

Server.cs

 using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    class Server
        {
            private Socket serverSocket;
            private Socket clientSocket;
            private IPAddress ipAddress;
            private IPEndPoint ipEndPoint;
            private List<Client> clientList = new List<Client>();
    
            public Server(string ip,int port)
            {
                //创建Socket
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //声明ip地址和端口号
                this.ipAddress = IPAddress.Parse(ip);
                this.ipEndPoint = new IPEndPoint(ipAddress, port);
            }
    
            public void Start()
            {
                //Socket绑定IP和端口号
                serverSocket.Bind(ipEndPoint);
                //Socket开始监听
                serverSocket.Listen(0);
    
                Console.WriteLine("服务器已经启动");
    
    
                //客户端接入
                serverSocket.BeginAccept(AcceptCallback,null);
            }
    
            private  void AcceptCallback(IAsyncResult ar)
            {
                clientSocket = serverSocket.EndAccept(ar);
                //获取客户端名称
                string clientName = clientSocket.RemoteEndPoint.ToString();
                Client client = new Client(clientSocket, clientName);
                client.Start();
                Console.WriteLine(clientName + "已经登录。。。");
    
                clientList.Add(client);
    
                //继续循环监听客户端的连接
                serverSocket.BeginAccept(AcceptCallback, null);
            }
        }

Server类的主要功能无非就是开启个Socket绑定确定的IP和端口,时刻监听客户端的连接。程序在这里采取的是异步方式,之所以代码上没有明显的线程调用,是因为在采用了封装好的API,像 BeginXXX 这样的函数,为了能够循环监听客户端的连接也是在AcceptCallback里面继续开启客户端的监听,大体的逻辑是这样。

而这里的Client类可不是代表实际意义上的客户端,这里只是对客户端进行的相关管理,主要是对客户端的消息发送和接收进行着处理,之所以采取两个类的方式,也是受到面向对象思想的影响,同样便于代码的管理。

Client.cs

 using System;
    using System.Text;
    using System.Net.Sockets;
    class Client
        {
            private Socket clientSocket;
            private string clientName;
            private byte[] recieveData;
    
            public Client(Socket client,string clientName)
            {
                this.clientSocket = client;
                this.clientName = clientName;
                recieveData = new byte[clientSocket.ReceiveBufferSize];
            }
    
            public void Start()
            {
                clientSocket.BeginReceive(recieveData,0, clientSocket.ReceiveBufferSize,SocketFlags.None, RecieveCallback, null);
            }
    
            //接收客户端的消息
            private void RecieveCallback(IAsyncResult ar)
            {
                try
                {
                    //接收到的数据长度
                    int count = clientSocket.EndReceive(ar);
    
                    //防止客户端异常退出
                    if (count == 0)
                    {
                        clientSocket.Close();
                        return;
                    }
    
                    //对接收到的数据进行处理
                    string msgRec = Encoding.UTF8.GetString(recieveData, 0, count);
                    HandleResponse(msgRec);
    
                    //输出到控制台
                    Console.WriteLine(msgRec);
    
                    //循环接收客户端发送过来的数据
                    clientSocket.BeginReceive(recieveData, 0, clientSocket.ReceiveBufferSize, SocketFlags.None, RecieveCallback, null);
                }
                catch (Exception)
                {
                    if (clientSocket != null)
                    {
                        clientSocket.Close();
                        return;
                    }
                }
                
            }
    
            //对客户端返回过来的数据进行处理
            private void HandleResponse(string data)
            {
                if (data.Equals("hello"))
                {
                    SendMessage("hello too");
                }else if (data.Equals("haha"))
                {
                    SendMessage("heihei");
                }
            }
    
            //发送消息给客户端
            private void SendMessage(string data)
            {
                byte[] msgData = Encoding.UTF8.GetBytes(data);
                clientSocket.Send(msgData);
            }
        }

服务器端对客户端发出的请求是在对消息解析后才处理的,也就是我们的HandleResponse函数里面,这里只是简单的对客户端发送过来的字符串进行简单的if else判断而已~

客户端创建

相对服务器端的构建,客户端算是简单了许多,这里也就只有一个类来测试的。

Client.cs

 using UnityEngine;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    using System;
    using UnityEngine.UI;
    public class Client : MonoBehaviour {
    
        private Socket clientSocket;
        private byte[] recieveData;
        private Button btn1;
        private Button btn2;
        // Use this for initialization
        void Start () {
    
            InitNet();
    
            btn1 = transform.Find("Btn1").GetComponent<Button>();
            btn2 = transform.Find("Btn2").GetComponent<Button>();
    
            btn1.onClick.AddListener(() => {
                SendMsg("hello");
            });
    
            btn2.onClick.AddListener(() => {
                SendMsg("haha");
            });
        }
    
        private void InitNet()
        {
            // 首先声明一个Socket
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //申明IP和端口号
            IPAddress iPAddress = IPAddress.Parse("127.0.0.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 8899);
            //连接服务器端
            clientSocket.Connect(iPEndPoint);
    
            //接收服务端发送过来的消息
            recieveData = new byte[clientSocket.ReceiveBufferSize];
            clientSocket.BeginReceive(recieveData, 0, clientSocket.ReceiveBufferSize, SocketFlags.None, RevieveCallback, null);
        }
    
        private void RevieveCallback(IAsyncResult ar)
        {
            int count = clientSocket.EndReceive(ar);
            string msgRec = Encoding.UTF8.GetString(recieveData, 0, clientSocket.ReceiveBufferSize);
            //输出信息
            Debug.Log(msgRec);
            recieveData = new byte[clientSocket.ReceiveBufferSize];
            clientSocket.BeginReceive(recieveData, 0, clientSocket.ReceiveBufferSize, SocketFlags.None, RevieveCallback, null);
        }
    
        private void SendMsg(string data)
        {
            byte[] sendMsg = Encoding.UTF8.GetBytes(data);
            clientSocket.Send(sendMsg);
        }
    }


在客户端初始Socket,确认IP和端口号就能连上服务器了,然后通过Unity的组件进行消息的发送,然后接收相关消息,流程一步了然,简直不要太简单~

源码地址

源码工程已上传Github了,在这里

总结

通过这个小的实例可以了解到Socket的基本编程,以及简单的网络通信,当然这只是在局域网下能够通信哈,而后博主也是会加大难度,基于此开发一个网络游戏,在广域网下也能完美运行(当然现在服务器都没有233333)

就这么多,白了个白~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 今天实例是在之前的基础上添加了新的功能,所以不止简单的字符串通信,可以说得上是我们联机游戏中角色的信息同步功能的缩...
    牛水聿阅读 807评论 0 8
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,431评论 25 707
  • 1、TCP状态linux查看tcp的状态命令:1)、netstat -nat 查看TCP各个状态的数量2)、lso...
    北辰青阅读 9,392评论 0 11
  • “有些路,只能一个人走”。这是《目送》里最触动我心灵的一句话。 父母,他们再爱我,如无意外,不会陪我走到人生的终点...
    烟火文苑菜包包阅读 279评论 0 4