前言
虽然最爱单机游戏,但是和朋友一起玩联网游戏可以获得双倍快乐!所以开始学习网络游戏相关的知识啦
1.1藏在幕后的服务端
客户端和客户端之间通过服务端的消息转发进行通信。
为了支撑很多玩家,游戏服务端通常采取分布式架构,也就是分区服务端,每个服务端负责不同区的玩家。
服务端和服务端之间通常使用TCP通信。
1.2网络连接的端点:Socket
网络上的两个程序通过一个双向的通信连接实现数据交换,这个连接的一端称为一个Socked。
每个Socket包含五种必备信息:
- 连接使用的协议:TCP
- 本地IP:192.168.200.11
- 本地端口:1000
- 远程IP:192.168.200.20
- 远程端口:800
两个不同主机的引用程序相互通信,就是先通过IP地址获取对方的计算机,再通过每个端口号获取这台计算机上的应用程序进行通信。(每个Socket连接都是从一台计算机的一个端口连接到另外一台计算的某个端口)
1.2.4Socket通信的流程
- 创建Socket对象,绑定本地端口(Bind),对于客户端而言,连接时(Connect)会由系统分配端口,可以省略绑定
- 服务端开启监听,等待客户端接入
- 客户端连接服务器
- 服务器接受连接
- 客户端和服务端通过Send和Receive手法数据,操作系统下自动完成数据确认、重传等
- 某一方Close连接,自动四次挥手
1.3开始网络编程:Echo
笔记均在代码注释中
1.3.1客户端代码
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 InputField;
public Text text;
//点击连接按钮
public void Connection()
{
//新建sockect
//地址族IPV4,套接字类型stream,协议类型
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//connect
//远程IP地址,远程端口,阻塞方法,卡住直到服务端回应、
//自己建立服务器的话,ip地址和端口号就是这两个
socket.Connect("127.0.0.1", 8888);
}
//点击发送按钮
public void Send()
{
//send
//string sendStr = InputField.text;
string sendStr = System.DateTime.Now.ToString();
//将str转化为字节流
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.3.2服务端代码
using System;
using System.Net;
using System.Net.Sockets;
namespace ConsoleApp1
{
class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Hello");
//Socket
Socket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind
IPAddress ipAdr = IPAddress.Parse("127.0.0.1");//IP地址
IPEndPoint ipEp = new IPEndPoint(ipAdr, 8888);//IP和端口
//给listenfd套接字绑定IP和端口,"127.0.0.1"地址和8888号端口
listenfd.Bind(ipEp);
//Listen,等待客户端连接
//0表示容纳等待接收的客户端连接数不受限制,1代表最多可容纳等待接受的连接数为1
listenfd.Listen(0);
Console.WriteLine("[服务器]启动成功");
while (true)
{
//Accept
//接收客户端连接,均为阻塞方法,如果没有客户端连接就不会向下执行
//返回一个新客户端的socket对象,对于服务器来说
//它有一个监听 Socket(listenfd)用来监听和应答客户端的连接,对每个客户端还有专门一个socket(connfd)用于处理客户端的数据
Socket connfd = listenfd.Accept();
Console.WriteLine("[服务器]Accetp");
//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);
}
}
}
}
结果
1.5公用网和局域网
如果是校园网的局域网内,把服务端放到连接校园网的计算机上,因为只有局域网IP,所以只有局域网内的计算机可以连接上。但是有“端口映射”技术。
如果没有路由器的控制权(校园网),就要将服务端程序部署到阿里云、腾讯云等云服务器。