第二章节>>现学现卖掌握快
唠嗑一下。大学毕竟不全是荒度。“查找文献->综述->论文”这个“三段式”是记住了,感谢胡导师!
实现思路:
服务端是需要一直监听的,所以监听需要用一个线程(thread)来单独处理,然后在主线程里处理客户端的发送过来的数据。while(true)永真式保证监听的持续性,Socket里面的accept阻塞方法让该循环不至于为死循环,剩下的就是API的调用。
(代码来源:http://www.manew.com/thread-102109-1-1.html Unity3d基于Socket通讯例子)
打包一:客户端服务端一体:
打包二:客户端:
勾掉服务端的代码,打包。先运行服务端,再运行客户端
服务端界面:
最终效果:
/*
/下面就是直接手动Copy大佬的demo
*/
- –<<服务端>>–
<监听客户端>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System;
using System.Net;
using System.Net.Sockets;
namespace XJH
{
public class NewServer : MonoBehaviour
{
private const int _port = 9999;//服务器监听的端口
public static string IP
{
get
{
return "127.0.0.1";
}
}//服务器ip 直接设置成const也行,不过属性能查找引用
Thread _listenClient;//监听客户端的一个线程
void Start()
{
_listenClient = new Thread(ListenClientConnet);//用线程监听客户端
_listenClient.Start();//Start,开启线程
}
private void ListenClientConnet()
{
try
{
IPAddress serverIP = IPAddress.Parse(IP);//将IP字符串转换
TcpListener tcpListener = new TcpListener(serverIP, _port);//实例化一个监听端口
tcpListener.Start();//开始监听
//一直监听
while (true)
{
NewChatClient user = new NewChatClient(tcpListener.AcceptTcpClient());//AcceptTcpClient阻塞方法
Debug.Log(user._clientIP + ": get in\n");
}
}
catch (Exception e)
{
Debug.Log("Server Listen error: " + e.Message);
}
}
}
}
<响应客户端>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System;
namespace XJH
{
public class NewChatClient : MonoBehaviour
{
public static Hashtable _AllClients = new Hashtable();//客户端列表
private TcpClient _client;//客户端对象
public string _clientIP;//客户端IP
private string _clientName;//用户名
private byte[] _data;//消息数据
private bool _receiveName = true;//接收客户端的开关
private void Start()
{
}
public NewChatClient(TcpClient client)
{
_client = client;
_clientIP = client.Client.RemoteEndPoint.ToString();
_AllClients.Add(_clientIP, this);//添加IP字符串和脚本实例
_data = new byte[_client.ReceiveBufferSize];//动态创建相应大小的字符数组
//从服务端获取消息
//参数列表:字符数组,偏移量,读取的长度,
//委托(返回类型void,参数列表为IAsyncResult(接口,里面包含一些只读属性))
//一个object类型的自定义状态
_client.GetStream().BeginRead(_data, 0,
System.Convert.ToInt32(_client.ReceiveBufferSize), ResiveMessage, null);
}
public void ResiveMessage(IAsyncResult ar)
{
int bytesRead;
try
{
lock (_client.GetStream())
{
bytesRead = _client.GetStream().EndRead(ar);
}
if (bytesRead < 1)//没东西
{
_AllClients.Remove(_clientIP);//哈希表里移除这个IP
Broadcast(_clientName + ": get out");//断开服务器
return;
}
else//接收到消息内容
{
string msgResived = Encoding.UTF8.GetString(_data, 0, bytesRead);//接收到的信息(byte转成UTF-8)
if (_receiveName)//只执行一次
{
_clientName = msgResived;//用户名赋值
Broadcast(_clientName + ": get in");//连接服务器
_receiveName = false;
}
else
{
Broadcast(_clientName + " --> " + msgResived);//输出分发的消息
}
}
lock (_client.GetStream())
{
_client.GetStream().BeginRead(_data, 0, System.Convert.ToInt32(_client.ReceiveBufferSize),
ResiveMessage, null);
}
}
catch(Exception e)
{
_AllClients.Remove(_clientIP);
Broadcast(_clientName + ": get out");
}
}
//向客户端发送消息
public void SendMsg(string msg)
{
try
{
NetworkStream ns;
lock (_client.GetStream())
{
ns = _client.GetStream();
}
byte[] bytesToSend = Encoding.UTF8.GetBytes(msg);
ns.Write(bytesToSend, 0, bytesToSend.Length);
ns.Flush();
}
catch (Exception e)
{
Debug.Log("Error: " + e);
}
}
//向客户端广播消息
public void Broadcast(string msg)
{
Debug.Log(msg);
foreach (DictionaryEntry c in _AllClients)
{
((NewChatClient)(c.Value)).SendMsg(msg + Environment.NewLine); //Environment.NewLine:回车,换行
}
}
}
}
- –<<客户端>>–
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace XJH
{
public class NewClientHandler : MonoBehaviour {
private string _ip = "127.0.0.1";
private int _port = 9999;
private TcpClient _client;
private byte[] _data;
public string _userName;
public string _msg;
public string _sendMsg;
private void OnGUI()
{
_userName = GUI.TextField(new Rect(10, 10, 100, 20), _userName);
_msg = GUI.TextArea(new Rect(10, 40, 300, 200), _msg);
_sendMsg = GUI.TextField(new Rect(10, 250, 210, 20), _sendMsg);
if (GUI.Button(new Rect(120, 10, 80, 20), "Connet"))
{
_client = new TcpClient();
_client.Connect(_ip, _port);
_data = new byte[_client.ReceiveBufferSize];
SendMyMsg(_userName);
_client.GetStream().BeginRead(_data, 0, System.
Convert.ToInt32(_client.ReceiveBufferSize), ReceiveMessage, null);
}
if (GUI.Button(new Rect(230, 250, 80, 20), "Send"))
{
SendMyMsg(_sendMsg);
_sendMsg = "";
}
}
public void SendMyMsg(string msg)
{
try
{
NetworkStream ns = _client.GetStream();
byte[] data = Encoding.UTF8.GetBytes(msg);
ns.Write(data, 0, data.Length);
ns.Flush();
}
catch (Exception e)
{
Debug.Log("Error: " + e);
}
}
public void ReceiveMessage(IAsyncResult ar)
{
try
{
int bytesRead = _client.GetStream().EndRead(ar);
if (bytesRead < 1)
{
return;
}
else
{
_msg += Encoding.UTF8.GetString(_data, 0, bytesRead).ToString();
}
_client.GetStream().BeginRead(_data, 0, System.Convert.ToInt32(_client.ReceiveBufferSize), ReceiveMessage, null);
}
catch (Exception e)
{
print("Error: " + e);
}
}
}
}