【Unity3D】Socket通讯(1)——连接

    xiaoxiao2021-03-26  35

    【准备】

    游戏引擎:Unity3D - 5.4.1

    脚本编辑器:Visual Studio 2012

    脚本语言:C#

    【前言】

      亦泽将会开设Socket系列博文来记录自己学习Socket通讯知识的情况,并为大家粗浅的介绍Socket相关内容。关于这方面亦泽掌握的知识既不深也不多,毕竟不是专做网络这方面,但是了解相关的基础知识还是很有必要的,从微观来说,可以为以后做的小项目增光添彩,从长远来说,对宏观思维能力有一定的提高。

    【理论】

    Socket定义:

      下述文字会有部分内容参考自百度百科,其余均为自己的理解,如果有较大偏差还请相关专业的读者给我留言。

      从专业定义角度:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的每一端都称为一个Socket。建立网络通信连接时至少要一对Socket(即客户端的Socke与服务器的Socket)。Socket本质是API(应用程序接口)。

      从通俗角度:Socket翻译为汉语为“孔,插座”,举个例子,一个插排我们可以想象它就是服务器,它有很多插口,每个插口就是一个Socket,有的插口用于给手机充电,有的插口用于给Pad充电,有的插口用于给电视机供电,那么手机Pad电视机这些就相当于不同的客户端(准确来说是不同的应用程序,因为“一个客户端”这样的词汇往往会使人联想到是一台客户的电脑,但是一台电脑上可以有许多的应用进程,每个与远程服务器有连接关系的都是一个Socket),连接服务器和客户端的两个端点都是Socket。

      在对Socket有了基本的认识后,就要进入我们本次实战的主题——服务器与客户端的连接。

    连接过程:

      服务器监听——客户端请求——连接确认。

    过程描述:

      服务器会创建Socket实例,然后处于等待连接的状态也就是监听状态,当客户端的Socket指出服务器的IP和端口后,即可向服务器发出连接请求,服务器为请求连接的客户端创建一个Socket(此时服务器和客户端一般都需要单独开启一个线程来处理通信),完成双向连接,此时服务器可继续监听是否有客户端连接。

    具体细节:

    一,服务器部分

    1、创建Socket实例,为其指定协议族,类型,以及协议。

      我们这边通常使用的TCP/IP协议,是一种面向连接的、可靠的、面对字节流的传输方式,所以协议我们指定为TCP协议;协议族决定Socket的地址类型,我们这里采用Ipv4地址与端口号的组合;而且类型我们选择流(Stream)方式来完成,这是一种面向连接的方式。

    2、对地址和端口号进行绑定。

      我们可以打开cmd窗口输入ipconfig回车然后查看自己的网络IP是多少,然后端口号可以随便指定一个,端口号范围是(0~65535)建议指定为4位数以上(这样是避免端口号发生重复,端口号用于唯一标识当前电脑的某一应用进程,而有些端口号特别数值偏小的端口号已经被协议占用,比如80端口就是HTTP协议占用,而其他应用进程采用的端口号一般也是比较小的数字,所以我们自己学习时最好用四五位这样的端口号),利用IP和端口号的组合我们可以创建一个远程终结点,这个点唯一标识一个网络中的应用进程。然后我们使用Bind方法来绑定这个点来指定给服务器端的Socket。

    3、启用监听。

      可以使用Listen方法来开始监听,此时我们可以指定一个参数为最大链接数,控制服务器的负载。

    4、等待客户端连接。

      启动Accept方法,这个方法是一个阻塞方法,意思是如果没有客户端请求连接程序就会停留在这行代码,直到有客户端连接时才会执行下一行代码,这个方法具有Socket类的返回值,我们创建Socket实例来接收这个返回值,从而创建与客户端连接的Scoket端点。

    二,客户端部分

    1、与服务器部分第1步一致

    2、创建远程终结点。

      这一步在端口号和地址的部分与服务器部分一样。注意,这里创建的终结点的IP必须与服务器端一致,因为是客户端向服务器发起连接请求,客户端需要知道要连接的服务器终结点是什么才能发起请求。客户端不需要使用Bind方法绑定终结点。

    3、发起连接。

      使用Connect方法发起连接,参数为服务器的终结点。

    【实践】

    一.服务器:

    打开Visual Studio,创建C#的控制台程序,创建好后如图所示。

    添加如下代码(主要代码上方均有注释):

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Net.Sockets; namespace Socket_ArtCreateSpace { class Program { //注:这里的ip设置为你自己电脑的ip,查询方法在上周推文中有 const string _ip = "192.168.1.107"; const int _port = 7788; static void Main(string[] args) { //创建服务器端的Socket的实例 Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建终结点需要IPAddress类型的对象来表示ip //可以用Parse方法将ip字符串转化为IPAddress类型的点分十进制的ipv4地址 IPAddress ipAddress = IPAddress.Parse(_ip); //创建终结点,绑定IP和端口号 IPEndPoint ipPoint = new IPEndPoint(ipAddress, _port); //绑定终结点,使其作为服务器进程在网络中的唯一标识 serverSocket.Bind(ipPoint); //开始监听,并指定最大连接数 serverSocket.Listen(100); Console.WriteLine("Server socket is running......"); //Accept方法会阻塞程序运行,如果有客户端请求连接 //连接成功后这个方法返回一个Socket,以此创建与客户端连接的端点 //然后执行下一条打印的语句 Socket clientSocket = serverSocket.Accept(); Console.WriteLine("A client is connected!"); Console.ReadKey(); } } }

    注:Socket需要添加两个命名空间的引用,已在代码中给出

    运行程序,可以看到如图所示效果。

    保持此窗口一直打开,即我们的服务器端是开启着。

    二.客户端:

    新建Unity工程,然后直接创建脚本Client,添加如下代码:

    using UnityEngine; using System.Collections; using System.Net; using System.Net.Sockets; public class Client : MonoBehaviour { //客户端Socket对象 Socket clientSocket; //ip和端口号要与服务器端一致 const string _ip = "192.168.1.107"; const int _port = 7788; void Start () { //实例化Socket对象 clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //转化ip并创建远程终结点 IPAddress ipAddress = IPAddress.Parse(_ip); IPEndPoint ipPoint = new IPEndPoint(ipAddress, _port); //请求连接服务器 clientSocket.Connect(ipPoint); Debug.Log("Connect success!"); } }

      将此脚本场景中随便一个物体上,我这里挂到了摄像机上,运行游戏,同时观察服务器端和客户端,会发现服务器端和客户端打印如图所示,表明服务器与客户端连接成功。

    【结语】

      在Socket通讯中,连接虽然是最为基础的部分,但也是最重要的部分。连接功能不仅作为通讯的前提条件,也能直观的从连接功能中看出Socket应用进程间的通讯关系,以便在今后的网络相关开发中更好的理解主机间的逻辑关系。亦泽也是初学这部分,有喜欢这方面和相关专业的朋友可以联系亦泽,共同进步。最后,若文章有描述不够准确的地方还请大家多多包涵。

    【GitHub】

    https://github.com/Eazey/Socket_Connection.git

    转载请注明原文地址: https://ju.6miu.com/read-662073.html

    最新回复(0)