[Unity网络游戏实战]网络游戏的“Hello,World”——Echo(回响)(新手向)

网络游戏的“Hello,World”——Echo(回响)

1,Socket

1.1 Socket

网络上的两个程序通过一个双向的通信连接实现数据交换,这个连接的一端称为一个Socket。一个Socket包含了进行网络通信必需的五种信息:连接使用的协议、本地主机的IP地址、本地的协议端口、远程主机的IP地址和远程协议端口

image-20231221205108243

Socket理解成一台手机,那么本地主机IP地址和端口相当于自己的手机号码,远程主机IP地址和端口相当于对方的号码。至少需要两台手机才能打电话,同样地,至少需要两个Socket才能进行网络通信。

1.2 IP地址

网络上的计算机都是通过IP地址识别的,应用程序通过通信端口彼此通信

提示 在Windows命令提示符中输入ipconfig,便能够查看本机的IP地址。

在这里插入图片描述

1.3 端口

“端口”是英文port的意译,是设备与外界通信交流的出口。每台计算机可以分配0到65535共65536个端口。通俗地讲,每个Socket连接都是从一台计算机的一个端口连接到另外一台计算机的某个端口,

Socket→本地端口→网络介质→远程端口→远程Socket的链路

1.4 Socket通信流程

在这里插入图片描述

连接方(客户端)和监听方(服务端)有着不同的流程

1)开启一个连接之前,需要创建一个Socket对象(使用API Socket),然后绑定本地使用的端口(使用API Bind)。对服务端而言,绑定的步骤相当于给手机插上SIM卡,确定了“手机号”。对客户端而言,连接时(使用API Connect)会由系统分配端口,可以省去绑定步骤

2)服务端开启监听(使用API Listen),等待客户端接入。相当于电话开机,等待别人呼叫。

3)客户端连接服务器(使用API Connect),相当于手机拨号。进行三次握手连接

4)服务器接受连接(使用API Accept),相当于接听电话并说出“喂”。通过这4个步骤,成功建立连接,可以收发数据。

5)客户端和服务端通过SendReceive等API收发数据,操作系统会自动完成数据的确认、重传等步骤,确保传输的数据准确无误。

6)某一方关闭连接(使用API Close),操作系统会执行**“四次挥手**”的步骤,关闭双方连接,相当于挂断电话。

1.5 TCP和UDP协议

TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,与TCP相对应的**UDP协议是无连接的、不可靠的、但传输效率较高的协议。**在本章的语义中,“Socket通信”特指使用TCP协议的Socket通信。

2.3 开始网络编程:Echo

2.3.1 什么是Echo程序

Echo程序是网络编程中最基础的案例。建立网络连接后,客户端向服务端发送一行文本,服务端收到后将文本发送回客户端 。

在这里插入图片描述

Echo程序分为客户端和服务端两个部分,客户端部分使用Unity实现,为了技术的统一,服务端使用C#语言实现 。(现在大部分服务器由C++实现)

2.3.2 编写客户端程序

打开Unity,新建名为Echo的项目,制作简单的UGUI界面。在场景中添加两个按钮(右击Hierarchy面板,选择UI→Button,分别命名为ConnButton和SendButton。Unity会自动添加名为Canvas的画布和名为EventSystem的事件系统),添加一个输入框(命名为InputField)和一个文本框(命名为Text),如图所示。

在这里插入图片描述

#客户端代码 Echo.cs脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using UnityEngine.UI;
public class Echo : MonoBehaviour {
//定义套接字
Socket socket;
//UGUI
public InputField InputFeld;
public Text text;
//点击连接按钮
public void Connection()
{
//Socket
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//Connect
socket.Connect("127.0.0.1", 8888);
}
//点击发送按钮
public void Send()
{
//Send
string sendStr = InputFeld.text;
byte[] sendBytes =
System.Text.Encoding.Default.GetBytes(sendStr);
socket.Send(sendBytes);
//Recv
byte[] readBuff = new byte[1024];
int count = socket.Receive(readBuff);
string recvStr =
System.Text.Encoding.Default.GetString(readBuff, 0, count);
text.text = recvStr;
//Close
socket.Close();
}
}

(1)using System.Net.SocketsSocket编程的API(如Socket、AddressFamily等)位于System.Net.Sockets命名空间中,需要引用它。

(2)创建Socket对象

Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp)这一行用于创建一个Socket对象,它的三个参数分别代表地址族、套接字类型和协议。

·地址族指明使用IPv4还是IPv6,本例中使用的是IPv4,即InterNetwork。

·SocketType是套接字类型,游戏开发中最常用的是字节流套接字,即Stream。

·ProtocolType指明协议,本例使用的是TCP协议。若要使用传输速度更快的UDP协议而不是较为可靠的TCP,需要更改协议类型 。

(3)连接Connect

客户端通过socket.Connect(远程IP地址,远程端口)连接服务端。Connect是一个阻塞方法,程序会卡住直到服务端回应(接收、拒绝或超时)。

(4)发送消息Send

客户端通过socket.Send发送数据,这也是一个阻塞方法。该方法接受一个byte[]类型的参数指明要发送的内容。Send的返回值指明发送数据的长度(例子中没有使用)。程序用

System.Text.Encoding.Default.GetBytes(字符串)把字符串转换成byte[]数组,然后发送给服务端。

(5)接收消息Receive

客户端通过socket.Receive接收服务端数据。Receive也是阻塞方法,没有收到服务端数据时,程序将卡在Receive不会往下执行。Receive带有一个byte[]类型的参数,它存储接收到的数据。Receive的返回值指明接收到数据的长度。之后使用System.Text.Encoding.Default.GetString(readBuff,0,count)将byte[]数组转换成字符串显示在屏幕上。

(6)关闭连接Close

通过socket.Close关闭连接。

2.4 完成客户端

编写完代码后,将Echo.cs拖曳到场景中任一物体上,并且给InputField和Test两个属性赋值(将对应游戏物体拖曳到属性右侧的输入框上)在属性面板中给ConnButton添加点击事件,设置为Echo组件的Connection方法。使得玩家点击连接按钮时,调用Echo组件的Connection方法。采用同样的方法,给SendButton添加点击事件,设置为Echo组件的Send方法。

2.5 创建服务端

Visual Studio中创建C#项目

键入以下代码:

using System;
using System.Net;
using System.Net.Sockets;
namespace EchoServer
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Hello World!");
//Socket
Socket listenfd = new
Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//Bind
IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
IPEndPoint ipEp = new IPEndPoint(ipAdr, 8888);
listenfd.Bind(ipEp);//Listen
listenfd.Listen(0);
Console.WriteLine("[服务器]启动成功");
while (true) {
//Accept
Socket connfd = listenfd.Accept ();
Console.WriteLine ("[服务器]Accept");
//Receive
byte[] readBuff = new byte[1024];
int count = connfd.Receive (readBuff);
string readStr =
System.Text.Encoding.Default.GetString (readBuff, 0, count);
Console.WriteLine ("[服务器接收]" + readStr);
//Send
byte[] sendBytes =
System.Text.Encoding.Default.GetBytes (readStr);
connfd.Send(sendBytes);
}
}
}
}

2.5.1 服务端知识点

(1)绑定Bind

listenfd.Bind(ipEp)将给listenfd套接字绑定IP和端口。程序中绑定本地地址“127.0.0.1”和8888号端口。127.0.0.1是回送地址,指本地机,一般用于测试。读者也可以设置成真实的IP地址,然后在两台计算机上分别运行客户端和服务端程序。

(2)监听Listen

服务端通过listenfd.Listen(backlog)开启监听,等待客户端连接。参数backlog指定队列中最多可容纳等待接受的连接数,0表示不限制。

(3)应答Accep

开启监听后,服务器调用listenfd.Accept()接收客户端连接。本例使用的所有Socket方法都是**阻塞方法,也就是说当没有客户端连接时,服务器程序卡在listenfd.Accept()不会往下执行,直到接收了客户端的连接。**Accept返回一个新客户端的Socket对象,对于服务器来说,它有一个监听Socket(例子中的listenfd)用来监听(Listen)和应答(Accept)客户端的连接,对每个客户端还有一个专门的Socket(例子中的connfd)用来处理该客户端的数据。

(4)IPAddress和IPEndPoint

使用IPAddress指定IP地址,使用IPEndPoint指定IP和端口。

(5)System.Text.Encoding.Default.GetString

Receive方法将接收到的字节流保存到readBuff上,readBuff是byte型数组。GetString方法可以将byte型数组转换成字符串。同理, System.Text.Encoding.Default.GetBytes可以将字符串转换成byte型数组。

2.6 测试Echo程序

大功告成,启动服务端程序,点击客服端的连接,输入文本点击发送。

在这里插入图片描述

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值