1.3.1 什么是Echo程序
Echo程序是网络编程中最基础的案例。建立网络连接后,客户端向服务端发送一行文本,服务端收到后将文本发送回客户端
1.3.2 客户端代码
using System.Collections;using System.Collections.Generic;using System.Net.Sockets;using UnityEngine;using UnityEngine.UI;public class Echo : MonoBehaviour{//定义套接字Socket socket;//UGUIpublic InputField inputField;public Text text;/// <summary>/// 点击连接按钮/// </summary>public void Connection(){//Socketsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//Connectsocket.Connect("127.0.0.1", 8888);}/// <summary>/// 点击发送按钮/// </summary>public void Send(){//Sendstring sendStr = inputField.text;byte[] sendBytes = System.Text.Encoding.Default.GetBytes(sendStr);socket.Send(sendBytes);//Recybyte[] readBuff = new byte[1024];int count = socket.Receive(readBuff);string recvStr = System.Text.Encoding.Default.GetString(readBuff, 0, count);text.text = recvStr;//closesocket.Close();}}
1.3.3 客户端代码知识点
using System.Net.Sockets
创建socket对象
Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp)这一行用于创建一个Socket对象,它的三个参数分别代表地址族、套接字类型和协议。
地址族指明使用IPv4还是IPv6,其含义如表1-4所示,本例中使用的是IPv4,即InterNetwork。
SocketType是套接字类型,类型如表1-5所示,游戏开发中最常用的是字节流套接字,即Stream。
ProtocolType指明协议,本例使用的是TCP协议,部分协议类型如表1-6所示。若要使用传输速度更快的UDP协议而不是较为可靠的TCP(回顾1.2.5节的内容),需要更改协议类型“Socket(AddressFamily.InterNetwork,SocketType.Dgram, Protocol-Type.Udp)
连接Connect
客户端通过socket.Connect(远程IP地址,远程端口)连接服务端。Connect是一个阻塞方法,程序会卡住直到服务端回应(接收、拒绝或超时)
发送信息Send
客户端通过socket.Send发送数据,这也是一个阻塞方法。该方法接受一个byte[]类型的参数指明要发送的内容。Send的返回值指明发送数据的长度(例子中没有使用)。程序用System.Text.Encoding.Default.GetBytes(字符串)把字符串转换成byte[]数组,然后发送给服务端
接受信息Receive
客户端通过socket.Receive接收服务端数据。Receive也是阻塞方法,没有收到服务端数据时,程序将卡在Receive不会往下执行。Receive带有一个byte[]类型的参数,它存储接收到的数据。Receive的返回值指明接收到数据的长度。之后使用System.Text.Encoding. Default.GetString(readBuff,0, count)将byte[]数组转换成字符串显示在屏幕上。
关闭连接
1.3.6 服务端代码
using System;using System.Net;using System.Net.Sockets;namespace Echo{class Program{/// <summary>/// 服务器遵照Socket通信的基本流程,先创建Socket对象,/// 再调用Bind绑定本地IP地址和端口号,/// 之后调用Listen等待客户端连接。/// 最后在while循环中调用Accept应答客户端,回应消息/// </summary>/// <param name="args"></param>static void Main(string[] args){Console.WriteLine("Hello World");//SocketSocket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//BindIPAddress ipAdr = IPAddress.Parse("127.0.0.1"); //地址IPEndPoint ipEp = new IPEndPoint(ipAdr, 8888); //端口listenfd.Bind(ipEp); //Socket 绑定//Listenerlistenfd.Listen(0); //backLog指的是指定队列中最多可容纳等待接受的连接数,0表示不限制Console.WriteLine("服务器启动成功");while (true){//AcceptSocket connfd = listenfd.Accept();Console.WriteLine("服务器Accept");//Receivebyte[] readBuff = new byte[1024];int count = connfd.Receive(readBuff);string readStr = System.Text.Encoding.Default.GetString(readBuff, 0, count);Console.WriteLine("服务器接收" + readStr);//Sendbyte[] sendBytes = System.Text.Encoding.Default.GetBytes(readStr);connfd.Send(sendBytes);}}}}
1.3.7 服务端代码知识点
绑定Bind
listenfd.Bind(ipEp)将给listenfd套接字绑定IP和端口。程序中绑定本地地址“127.0.0.1”和8888号端口。127.0.0.1是回送地址,指本地机,一般用于测试。读者也可以设置成真实的IP地址,然后在两台计算机上分别运行客户端和服务端程序。
监听Listen
服务端通过listenfd.Listen(backlog)开启监听,等待客户端连接。参数backlog指定队列中最多可容纳等待接受的连接数,0表示不限制
应答Accept
开启监听后,服务器调用listenfd.Accept()接收客户端连接。本例使用的所有Socket方法都是阻塞方法,也就是说当没有客户端连接时,服务器程序卡在listenfd.Accept()不会往下执行,直到接收了客户端的连接。Accept返回一个新客户端的Socket对象,对于服务器来说,它有一个监听Socket(例子中的listenfd)用来监听(Listen)和应答(Accept)客户端的连接,对每个客户端还有一个专门的Socket(例子中的connfd)用来处理该客户端的数据
IPAddress和IPEndPoint
使用IPAddress指定IP地址,使用IPEndPoint指定IP和端口
System.Text.Encoding.Default.GetString
Receive方法将接收到的字节流保存到readBuff上,readBuff是byte型数组。GetString方法可以将byte型数组转换成字符串。同理,System.Text.Encoding.Default.GetBytes可以将字符串转换成byte型数组
