分为两个Unity项目
一个是SeverTest01 用于Unity的服务器部分 --------- 关于服务器部分的
一个是SocketTest01 用于Unity的客户端部分
初步学习只有简单的服务器和客户端连接,并且发送消息回复,算是一个学习记录
分为如下几个脚本 (Event脚本是固定的直接拖到Unity中即可)
依然还是 代码展示部分
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;
using UnityEngine;
using UnityEngine.UI;
public class Client : MonoBehaviour {
public InputField input;
public Text receiveText;
TcpSocket tcpClient;
private void Start()
{
//注册监听事件
receiveText = GameObject.Find("ReceiveText").GetComponent<Text>();
//回调函数有四个参数
EventDispatcher.AddEventListener<string>(EventKey.ServerCallBack, UpdateText);
//连接地址为家庭,类型为组,协议为Tcp
Socket client = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
tcpClient = new TcpSocket(client,1024,false);
}
/// <summary>
/// 一个具有参数的方法
/// </summary>
/// <param name="msg"></param>
private void UpdateText(string msg)
{
//receiveText.text = msg;
}
private void Update()
{
if (tcpClient != null && tcpClient.ClientConnect())
{
tcpClient.ClientReceive();
}
receiveText.text = DataManager.Instance.Msg;
}
/// <summary>
/// 设置IP地址,10086为端口号
/// </summary>
public void OnClickConnectBtn()
{
if (!tcpClient.ClientConnect())
{
tcpClient.ClientConnect("10.50.6.160", 10086);
}
}
/// <summary>
/// 注册Btn的点击事件
/// </summary>
public void OnClickToSendServer()
{
if (tcpClient != null && tcpClient.ClientConnect() && !String.IsNullOrEmpty(input.text))
{
tcpClient.ClientSeed(System.Text.Encoding.UTF8.GetBytes(input.text));
input.text = "";
}
}
/// <summary>
///
/// </summary>
private void OnApplicationQuit()
{
if (tcpClient != null && tcpClient.ClientConnect())
{
tcpClient.ClientClose();
}
}
/// <summary>
///
/// </summary>
private void OnDestroy()
{
EventDispatcher.RemoveEventListener<string>(EventKey.ServerCallBack, UpdateText);
}
}
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;
/// <summary>
/// 可以供客户端和服务器一块使用
/// </summary>
public class TcpSocket
{
//当前实例化的socket
private Socket socket;
//socket上的数据
private byte[] data;
//区别服务器 还是客户端
private bool isServer;
public TcpSocket(Socket socket,int dataLength ,bool isServer)
{
this.socket = socket;
data = new byte[dataLength];
this.isServer = isServer;
}
#region 接受
public void ClientReceive()
{
//data 数据缓存 0:指的是 接受位的偏移量 data.length指的是数据的长度 SocketFlags.None固定格式 new AsyncCallback(ClientEndReceive)需要有返回值的回调函数,返回值是下面的方法
//public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state);
socket.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ClientEndReceive), null);
}
public void ClientEndReceive(IAsyncResult ar)
{
//数据的处理
int receiveLength = socket.EndReceive(ar); //将接受到的数据赋值给receiveLength
//把接受完毕的字节数组转为string类型
string dataStr = System.Text.Encoding.UTF8.GetString(data, 0, receiveLength);
if (isServer) //判断是否接收到了因为开始设定了isServer是布尔值
{
Debug.Log("服务器接收到了:"+ dataStr);
//接受到了这里回复为
for (int i = 0; i < Server.Instance.clients.Count; i++)
{
if (Server.Instance.clients[i].ClientConnect())
{
Server.Instance.clients[i].ClientSeed(System.Text.Encoding.UTF8.GetBytes("服务器接收到了且回复:" + dataStr));
}
}
}
else
{
DataManager.Instance.Msg = dataStr;
Debug.Log("客户端接收到了:"+dataStr);
}
}
#endregion
#region 连接
public void ClientConnect(string ip, int port)
{
socket.BeginConnect(new IPEndPoint(IPAddress.Parse(ip),port),new AsyncCallback(ClientEndConnect),null);
}
public void ClientEndConnect(IAsyncResult ar)
{
if (ar.IsCompleted)
{
Debug.Log("连接成功");
}
socket.EndConnect(ar);
}
#endregion
#region 发送
public void ClientSeed(byte[] data)
{
socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ClientSeedEnd), null);
}
public void ClientSeedEnd(IAsyncResult ar)
{
socket.EndSend(ar);
}
#endregion
#region 断开
public bool ClientConnect()
{
return socket.Connected;
}
public void ClientClose()
{
if (socket != null && ClientConnect())
{
socket.Close();
}
}
#endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;
/// <summary>
/// 关于服务器的脚本
/// </summary>
public class Server : MonoBehaviour {
private static Server instance;
public static Server Instance
{
get
{
return instance;
}
}
private void Awake()
{
instance = this;
}
private Socket server;
//所有连接的客户端
public List<TcpSocket> clients;
private bool isLoopAccept = true;
private void Start()
{
//服务器socket 协议组 固定格式的协议组
server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//绑定端口号
server.Bind(new IPEndPoint(IPAddress.Any,10086));
//可以监听的客户端数目
server.Listen(100);
//开辟一个线程 用于处理客户端连接请求
Thread listenThread = new Thread(ReceiveClient);
//开启线程
listenThread.Start();
//后台运行
listenThread.IsBackground = true;
clients = new List<TcpSocket>();
}
private void ReceiveClient()
{
while (isLoopAccept)
{
//开始接受客户端连接请求
server.BeginAccept(AcceptClient,null);
//每隔一段时间检测有没有连接
Thread.Sleep(1000);
}
Debug.Log("检测客户端连接中...................");
}
private void AcceptClient(IAsyncResult ar)
{
Socket client = server.EndAccept(ar);
TcpSocket clientSocket = new TcpSocket(client,1024,true);
clients.Add(clientSocket);
Debug.Log("连接成功");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataManager {
private static DataManager instance;
public static DataManager Instance
{
get
{
if (instance == null)
{
instance = new DataManager();
}
return instance;
}
}
private DataManager()
{
}
private string msg;
public string Msg
{
get
{
return msg;
}
set
{
//表示数值有更新
if (msg != value)
{
msg = value;
EventDispatcher.TriggerEvent<string>(EventKey.ServerCallBack,msg);
}
}
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
UI部分也是很简单的搭了几个UI
注意:按钮的注册事件
还有这里
附
(项目链接:https://pan.baidu.com/s/16bi4JKJOmEqIom8Nnxv62A 提取码:gkr5 )