Socket 套接字 一个ip和一个端口组成一个Socket 属C/S架构 具有长连接和实时性(强联网) 客户端服务端都用Socket来声明 Socket类型又分为多种 常用有Stream流传输和Dgram打包传输 流传输对应协议类型的TCP(传输控制协议)Dgram打包传输对应协议类型的UDP(用户数据报协议)
TCP和UDP都是传输协议 双方通信时都需要端口的开放
TCP是可靠的传输 收发数据前先建立连接 UDP是不可靠的传输 不与对方建立连接 直接把数据报发出去
传输端口使用1024-65535
服务端和客户端都要创建Socket和绑定IP和端口 服务器用Bind绑定和Listen设置监听数量 通过Accept方法获取客户端并用Receive方法接收数据到缓冲区(byte数组) 解析消息头 switch/case分发执行不同操作 客户端封装数据压入字节流Send发送给已建立连接的服务端
TCP和UDP都是传输协议 双方通信时都需要端口的开放
TCP是可靠的传输 收发数据前先建立连接 UDP是不可靠的传输 不与对方建立连接 直接把数据报发出去
传输端口使用1024-65535
服务端和客户端都要创建Socket和绑定IP和端口 服务器用Bind绑定和Listen设置监听数量 通过Accept方法获取客户端并用Receive方法接收数据到缓冲区(byte数组) 解析消息头 switch/case分发执行不同操作 客户端封装数据压入字节流Send发送给已建立连接的服务端
异步(不用线程)Socket通信 定义字典存储一个ip对应一个Socket 服务端绑定ip和端口 开始连接BeginAccept 生成带IAsyncResult参数的回调函数 函数中存储ip对应的Socket 客户端开始接收数据BeginReceive 函数结束前递归调用BeginAccept 模拟线程 接收数据的回调函数中 接收完数据后放入缓冲区字节数组中 转换为字符串输出 回调函数结束之前 调用开始接收BeginReceive递归调用回调函数 模拟线程;发送消息时 将字符串转为字节数组用BeginSend开始发送 封装开始发送的回调函数 函数中输出向客户端发送的消息 服务端向所有与自己建立连接的客户端发消息时 遍历字典 调用发送消息的函数
客户端 定义TCPClient 接收队列和发送队列 以及字节数组用作缓冲区 首先client开始连接BeginConnect 成功建立连接之后可收发消息 接收消息时使用NetWorkStream开始读数据BeginRead 封装读数据的回调函数 发数据时压入队列 并在FixedUpdate中实时监测发送队列的长度 若压入数据则开始写入BeginWrite 发送数据
客户端 定义TCPClient 接收队列和发送队列 以及字节数组用作缓冲区 首先client开始连接BeginConnect 成功建立连接之后可收发消息 接收消息时使用NetWorkStream开始读数据BeginRead 封装读数据的回调函数 发数据时压入队列 并在FixedUpdate中实时监测发送队列的长度 若压入数据则开始写入BeginWrite 发送数据
线程通信实现同步 其实无固定的客户端与服务端 无论客户端还是服务端都可收发消息 客户端有多个 服务端有一个 客户端发送消息给服务端 服务端接收消息根据switch/case作出处理 再把做完处理的数据广播发送给所有客户端做到通信的同步 服务端从BeginAccept开始接收客户端的连接开始无限调用回调函数 连接之后调用接收数据函数 接收到数据做数据处理完毕的分发函数 服务端有储存所有客户端的字典 ip与Socket一一对应 遍历字典发送消息给所有客户端BeginSend ;客户端与服务端有共通之处可提出封装成一个通用类共同使用 客户端开始与服务端建立连接用BeginConnect 例如按钮点击发送消息 需要绑定点击事件 在点击事件的函数中获取流对象开始写入数据BeginWrite(即发送消息到服务端) 在与服务端建立连接之后 客户端开始用BeginRead接收服务端发来的消息 根据switch/case执行服务端发来的指令 并在客户端渲染出来
///服务端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
public class Server : MonoBehaviour
{
{
Socket server;
EndPoint point;
byte[] buf;
string host = "127.0.0.1";
short port = 8888;
EndPoint point;
byte[] buf;
string host = "127.0.0.1";
short port = 8888;
// Start is called before the first frame update
void Start()
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
point = new IPEndPoint(IPAddress.Parse(host), port);
server.Bind(point);
server.Listen(1);
buf = new byte[1024];
Debug.Log("wait for connecting");
server.BeginAccept(AcceptCallBack, server);
}
void Start()
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
point = new IPEndPoint(IPAddress.Parse(host), port);
server.Bind(point);
server.Listen(1);
buf = new byte[1024];
Debug.Log("wait for connecting");
server.BeginAccept(AcceptCallBack, server);
}
private void AcceptCallBack(IAsyncResult ar)
{
Socket server = (Socket)ar.AsyncState;
Socket client = server.EndAccept(ar);
Debug.Log(client.RemoteEndPoint.ToString() + "success connect");
client.BeginReceive(buf, 0, buf.Length, SocketFlags.None, RecvCallBack, client);
server.BeginAccept(AcceptCallBack, server);
}
{
Socket server = (Socket)ar.AsyncState;
Socket client = server.EndAccept(ar);
Debug.Log(client.RemoteEndPoint.ToString() + "success connect");
client.BeginReceive(buf, 0, buf.Length, SocketFlags.None, RecvCallBack, client);
server.BeginAccept(AcceptCallBack, server);
}
private void RecvCallBack(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int len = client.EndReceive(ar);
if (len > 0)
{
string msg = Encoding.UTF8.GetString(buf, 0, len);
Debug.Log("receive:" + msg);
SendMsg(msg, client);
}
{
Socket client = (Socket)ar.AsyncState;
int len = client.EndReceive(ar);
if (len > 0)
{
string msg = Encoding.UTF8.GetString(buf, 0, len);
Debug.Log("receive:" + msg);
SendMsg(msg, client);
}
}
public void SendMsg(string str,Socket item)
{
byte[] buffer = Encoding.UTF8.GetBytes(str);
item.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallBack, item);
}
{
byte[] buffer = Encoding.UTF8.GetBytes(str);
item.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallBack, item);
}
private void SendCallBack(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int len = client.EndSend(ar);
if (len > 0)
{
Debug.Log("成功发送" + len + "字节到客户端");
}
}
{
Socket client = (Socket)ar.AsyncState;
int len = client.EndSend(ar);
if (len > 0)
{
Debug.Log("成功发送" + len + "字节到客户端");
}
}
// Update is called once per frame
void Update()
{
}
}
void Update()
{
}
}
///客户端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
public class Client : MonoBehaviour
{
TcpClient client;
string host = "127.0.0.1";
short port = 8888;
byte[] buf;
bool flag = false;
// Start is called before the first frame update
void Start()
{
client = new TcpClient();
client.NoDelay = true;
buf = new byte[1024];
client.BeginConnect(IPAddress.Parse(host), port, ConnectCallBack, client);
}
{
TcpClient client;
string host = "127.0.0.1";
short port = 8888;
byte[] buf;
bool flag = false;
// Start is called before the first frame update
void Start()
{
client = new TcpClient();
client.NoDelay = true;
buf = new byte[1024];
client.BeginConnect(IPAddress.Parse(host), port, ConnectCallBack, client);
}
private void ConnectCallBack(IAsyncResult ar)
{
TcpClient client = (TcpClient)ar.AsyncState;
Debug.Log("success connect server");
NetworkStream ns = client.GetStream();
ns.BeginRead(buf, 0, buf.Length, ReadCallBack, ns);
}
{
TcpClient client = (TcpClient)ar.AsyncState;
Debug.Log("success connect server");
NetworkStream ns = client.GetStream();
ns.BeginRead(buf, 0, buf.Length, ReadCallBack, ns);
}
private void ReadCallBack(IAsyncResult ar)
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
int len = ns.EndRead(ar);
if (len > 0)
{
string msg = Encoding.UTF8.GetString(buf, 0, len);
Debug.Log("receive server message:"+msg);
if (msg == "rotate")
{
flag = true;
}
}
}
public void SendMsg(string str)
{
byte[] b = Encoding.UTF8.GetBytes(str);
NetworkStream ns = client.GetStream();
ns.BeginWrite(b, 0, b.Length, WriteCallBack, ns);
}
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
int len = ns.EndRead(ar);
if (len > 0)
{
string msg = Encoding.UTF8.GetString(buf, 0, len);
Debug.Log("receive server message:"+msg);
if (msg == "rotate")
{
flag = true;
}
}
}
public void SendMsg(string str)
{
byte[] b = Encoding.UTF8.GetBytes(str);
NetworkStream ns = client.GetStream();
ns.BeginWrite(b, 0, b.Length, WriteCallBack, ns);
}
private void WriteCallBack(IAsyncResult ar)
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
ns.EndWrite(ar);
}
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
ns.EndWrite(ar);
}
// Update is called once per frame
void Update()
{
if (flag)
{
GameObject.Find("Cube2").transform.Rotate(Vector3.up, 5);
}
}
}
void Update()
{
if (flag)
{
GameObject.Find("Cube2").transform.Rotate(Vector3.up, 5);
}
}
}