我們知道 除了單機游戲 其他所有游戲都是需要網絡通信的 跟其他用戶去交互 最近跟著大神老師學習了Socket 接下來 就和大家分享一下 如何用Socket實現簡單的本地聊天功能(這只是Socket入門的小玩意讓你理解了解一下 如果真正用到Socket 這個demo實在是拿不出手)
首先給大家看下效果:
下面介紹腳本 一共有四個腳本
有序列表
1.SocketFrameworkUse腳本 (見圖1 掛在Control上 它是一個空物體 下放了圖上的ui控件)
2.SocketFramework腳本 核心腳本(支撐腳本 無須掛在游戲對象上)
3.ServerControl腳本(見圖2 2.1 掛在ServerControl上 它是一個空物體 下放了圖上的ui控件)
4.PortControl腳本(見圖3 3.1 掛在PortControl上 它是一個空物體 下放了圖上的ui控件)
-
圖3 和圖2 不一樣 一個是客服端的發送界面 一個是接收端界面
4.jpg
圖1
圖2 2.1
圖3 3.1
下面是各個腳本代碼 注意 public GameObject對象全部是從面板拖進去的 沒有用代碼找到該對象
引用1.SocketFramework腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
/// <summary>
/// 消息回調
/// </summary>
public delegate void SocketCallback(string msg);
public class SocketFramework {
private static SocketFramework ins;
public static SocketFramework GetIns ()
{
if (ins == null)
{
ins = new SocketFramework ();
}
return ins;
}
private SocketFramework(){}
#region 服務器端
//聲明一個服務器套接字
private Socket serverSocket;
//服務器回調
private SocketCallback serverCallback;
//服務器消息緩存
private byte[] serverBuffer;
//已連接的Socket
private Socket m_workingSocket;
public void ServerInit(SocketCallback cb)
{
//定義Buffer長度
serverBuffer = new byte[100];
//接收回調
serverCallback = cb;
//1、初始化Socket
serverSocket = new Socket (AddressFamily.InterNetwork/*地址族:IPV4*/,
SocketType.Stream/*雙向讀寫流*/, ProtocolType.Tcp/*傳輸層使用協議*/);
//定義一個網絡節點
IPEndPoint ep = new IPEndPoint(IPAddress.Any/*選擇已經連接到互聯網的最優的網絡地址*/,23456);
//2、綁定網絡節點
serverSocket.Bind (ep);
//3、設置異步監聽數量
serverSocket.Listen(20);
//向上層發送服務器創建成功的消息
serverCallback("Server Has Init!!!" );
//4、異步接受客戶端的連接請求
serverSocket.BeginAccept(ServerAcceptCallback,serverSocket);
}
/// <summary>
/// 異步接受消息的回調
/// </summary>
/// <param name="ar">Ar.</param>
private void ServerAcceptCallback(System.IAsyncResult ar)
{
//獲取當前的套接字
Socket currentSocket = ar.AsyncState as Socket;
//結束接受請求
m_workingSocket = currentSocket.EndAccept (ar);
////向上層發送接受到客戶端的消息
serverCallback("Accept Client:" + m_workingSocket.LocalEndPoint);
//5、開啟異步接收客戶端的消息
m_workingSocket.BeginReceive (serverBuffer/*消息緩存*/, 0/*消息起始點*/,serverBuffer.Length/*消息長度*/
, SocketFlags.None/*消息標志位*/, ServerReceiveCallback/*消息回調*/, m_workingSocket);
//尾遞歸
//4、異步接受客戶端的連接請求
serverSocket.BeginAccept(ServerAcceptCallback,serverSocket);
}
/// <summary>
/// 異步接收消息的回調
/// </summary>
/// <param name="ar">Ar.</param>
private void ServerReceiveCallback(System.IAsyncResult ar)
{
//接收套接字
Socket workingSocket = ar.AsyncState as Socket;
//結束接收消息
int count = workingSocket.EndReceive (ar);
//將消息取出
string currentMsg = UTF8Encoding.UTF8.GetString(serverBuffer);
//清空緩存
serverBuffer = new byte[100];
//將接收到的消息傳到上層
serverCallback ("ReveiveMsg From " + workingSocket.LocalEndPoint + " Data:" + currentMsg);
//尾遞歸
//5、開啟異步接收客戶端的消息
workingSocket.BeginReceive (serverBuffer/*消息緩存*/, 0/*消息起始點*/,serverBuffer.Length/*消息長度*/,
SocketFlags.None/*消息標志位*/, ServerReceiveCallback/*消息回調*/, workingSocket);
}
/// <summary>
/// 服務器發送消息方法
/// </summary>
/// <param name="msg">Message.</param>
public void ServerSend(string msg)
{
//將要發送的消息轉成比特流
serverBuffer = UTF8Encoding.UTF8.GetBytes (msg);
//異步發送
m_workingSocket.BeginSend (serverBuffer, 0, serverBuffer.Length, SocketFlags.None, ServerSendCallback, m_workingSocket);
//將發送消息的信息發送上層
serverCallback("Server Send Msg : " + msg);
}
/// <summary>
/// 服務器異步發送的回調
/// </summary>
/// <param name="ar">Ar.</param>
private void ServerSendCallback(System.IAsyncResult ar)
{
Socket workingSocket = ar.AsyncState as Socket;
//服務器結束發送消息
int count = workingSocket.EndSend (ar);
}
#endregion
#region 客戶端
//客戶端套接字
private Socket clientSocket;
//客戶端回調
private SocketCallback clientCallback;
//客戶端緩存
private byte[] clientBuffer;
public void ClientConnect(string serverIp,int serverPort, SocketCallback cb)
{
//注冊客戶端回調
clientCallback = cb;
//初始化緩存
clientBuffer = new byte[100];
//1、初始化客戶端Socket
clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//2、連接服務器
clientSocket.BeginConnect (new IPEndPoint (IPAddress.Parse (serverIp), serverPort)/*服務器的網絡節點*/,
ClientConnectCallback, clientSocket);
}
/// <summary>
/// 客戶端連接的回調
/// </summary>
/// <param name="ar">Ar.</param>
private void ClientConnectCallback(System.IAsyncResult ar)
{
//連接好的套接字
Socket connectSocket = ar.AsyncState as Socket;
//向上層發送連接成功的消息
clientCallback ("Has Connect To Server : " + connectSocket.LocalEndPoint);
//結束連接
connectSocket.EndConnect (ar);
//3、開啟異步接收消息
connectSocket.BeginReceive(clientBuffer,0,clientBuffer.Length,SocketFlags.None,ClientReceiveCallback,connectSocket);
}
/// <summary>
/// 客戶端異步接收消息的回調
/// </summary>
/// <param name="ar">Ar.</param>
private void ClientReceiveCallback(System.IAsyncResult ar)
{
Socket workingSocket = ar.AsyncState as Socket;
//接收完畢
int count = workingSocket.EndReceive (ar);
//取出消息
string data = UTF8Encoding.UTF8.GetString(clientBuffer);
//接收到消息
clientCallback ("ReceiveMsg : " + data);
//清空
clientBuffer = new byte[100];
//尾遞歸
//3、開啟異步接收消息
workingSocket.BeginReceive(clientBuffer,0,clientBuffer.Length,SocketFlags.None,ClientReceiveCallback,workingSocket);
}
/// <summary>
/// 客戶端發送方法
/// </summary>
/// <param name="msg">Message.</param>
public void ClientSend(string msg)
{
//將字符串轉成比特流
clientBuffer = UTF8Encoding.UTF8.GetBytes (msg);
//4、異步發送
clientSocket.BeginSend (clientBuffer, 0, clientBuffer.Length, SocketFlags.None, ClientSendCallback, clientSocket);
}
/// <summary>
/// 客戶端發送回調
/// </summary>
/// <param name="ar">Ar.</param>
private void ClientSendCallback(System.IAsyncResult ar)
{
Socket workingSocket = ar.AsyncState as Socket;
//結束發送
workingSocket.EndSend (ar);
}
#endregion
}
引用2.SocketFrameworkUse腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI ;
using UnityEngine.SceneManagement ;
public class SocketFrameworkUse : MonoBehaviour {
public static SocketFrameworkUse Instant;
public InputField ipField;
public InputField portField;
public GameObject ServerControl ;
public GameObject PortControl;
//網絡狀態(0表示未連接,1表示服務器,2表示客戶端)
int networkState = 0;
#region UI變量
string clientConnectIP = "10.0.158.88" ;
string clientConnectPort = "23456" ;
string msgText = "" ;
public string currentMsg="" ;
#endregion
void Awake()
{
Instant = this;
}
void Start()
{
Application.runInBackground = true ;
}
void MsgCallback(string msg)
{
currentMsg += msg + "\n" ;
}
// 我是服務端調按鈕回調
public void ServerBnt()
{
// 初始化服務器
SocketFramework.GetIns().ServerInit(MsgCallback);
// 跳到服務端界面
ServerControl.SetActive (true);
gameObject.SetActive (false);
}
// 我是接收端按鈕回調方法
public void PortBtn()
{
clientConnectIP = ipField.text;
clientConnectPort = portField.text;
SocketFramework.GetIns ().ClientConnect (clientConnectIP,
int.Parse (clientConnectPort), MsgCallback);
PortControl.SetActive (true);
gameObject.SetActive (false);
}
}
引用3.ServerControl腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI ;
public class ServerControl : MonoBehaviour {
public InputField sendField;
void Awake()
{
gameObject.SetActive (false);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
// 服務端發送消息按鈕回調
public void SendMessage()
{
string msgText = sendField.text;
SocketFramework.GetIns ().ServerSend (msgText);
}
void OnGUI()
{
//顯示所有消息
GUILayout.Label (SocketFrameworkUse.Instant.currentMsg);
}
}
引用4.PortControl腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI ;
public class PortControl : MonoBehaviour {
public InputField sendField;
void Awake()
{
gameObject.SetActive (false);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
// 接收端發送消息按鈕回調
public void SendMessage()
{
string msgText = sendField.text;
SocketFramework.GetIns ().ClientSend (msgText);
}
void OnGUI()
{
//顯示所有消息
GUILayout.Label ( SocketFrameworkUse.Instant.currentMsg);
}
}