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);
}
}
}
