客户端:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class ClientCore : MonoBehaviour {
public static ClientCore instance = null;
//建立的通讯
private TcpClient client;
//Stream流
private NetworkStream stream;
//连接是否处于活动中
private bool __connected = false;
public bool connected
{
get { return __connected; }
}
//接受队列
public Queue<string> recvQueue = new Queue<string>();
//发送队列
public Queue<string> sendQueue = new Queue<string>();
//缓存区大小
private int maxBufferSize = 4096;
//线程
public Thread clientThread = null;
//是否停止线程
private volatile bool stop = false;
//全局唯一性
private void Awake () {
if (instance != null)
{
Debug.Log("严重 : ClientCore已经存在!");
DestroyImmediate(gameObject);
}else
{
DontDestroyOnLoad(gameObject);
instance = this;
}
}
private void Start()
{
instance = this;
//stop = false;
//开启客户端主线程
clientThread = new Thread(new ThreadStart(StartClient));
clientThread.IsBackground = true; //设为后台线程,伴随主线程关闭而关闭
clientThread.Start();
}
//socket连接是否有效
bool IsOpen()
{
return !((client.Client.Poll(1000, SelectMode.SelectRead) && (client.Client.Available == 0)) || !client.Client.Connected);
}
//Client线程
void StartClient()
{
byte[] recvBuf = new byte[maxBufferSize];
while (!stop)
{
if (!__connected)
{
//尝试开启一个连接
TryConnect();
}
//检查发送队列
if (sendQueue.Count > 0 && __connected)
{
byte[] buffer = Encoding.UTF8.GetBytes(sendQueue.Dequeue());
stream.Write(buffer, 0, buffer.Length);
stream.Flush();
}
//检查流接受数据
if (stream.DataAvailable && __connected)
{
int bytesRead = stream.Read(recvBuf, 0, maxBufferSize); //从流中获取数据,阻塞方法(如果没有数据,将阻塞线程)
if (bytesRead > 0)
{
string message = Encoding.UTF8.GetString(recvBuf);
Debug.Log("收到服务器消息:" + message);
recvQueue.Enqueue(message);
}
}
//线程暂停时间(毫秒)
Thread.Sleep(10);
}
//Close();
}
//尝试创建连接
public void TryConnect()
{
CreateConnection(NetworkValue.ip, NetworkValue.port);
}
void CreateConnection(string host, int port)
{
try
{
client = new TcpClient();
client.NoDelay = true;
//client.Connect(IPAddress.Parse(host), port);
IAsyncResult result = client.BeginConnect(IPAddress.Parse(host), port, null, null);
__connected = result.AsyncWaitHandle.WaitOne(1000, false);
if (__connected)
{
Debug.Log("连接成功!");
client.EndConnect(result);
}
else
{
Debug.Log("连接失败!");
client.Close();
}
}
catch (SocketException ex)
{
__connected = false;
Debug.Log("警告:连接出现异常--> " + ex.Message);
client.Close();
return;
}
if (__connected)
{
stream = client.GetStream();
}
}
//将消息加入发送队列
public static void Send(string item)
{
if (instance != null)
instance.Write(item);
}
void Write(string item)
{
sendQueue.Enqueue(item);
}
//从接收队列获取一条消息
public static string Recv()
{
if(instance!=null && instance.recvQueue.Count > 0)
{
return instance.recvQueue.Dequeue();
}
return null;
}
//防止程序没有正确退出
void OnApplicationQuit()
{
stop = true;
if (__connected)
{
__connected = false;
stream.Close();
client.Close();
}
if (clientThread != null && clientThread.IsAlive)
{
clientThread.Abort();
// 如果没有正确关闭线程,这里的Join就会阻塞,就会卡死编辑器
// recvProcess.Join();
Debug.Log("clientThread: " + clientThread.IsAlive);
}
}
void OnDestroy()
{
Debug.Log("Client OnDestroy");
OnApplicationQuit();
}
}
服务器端:
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class ServerCore : MonoBehaviour {
public static ServerCore instance = null;
//服务器监听端
private TcpListener listener = null;
//服务器主线程
private Thread serverThread = null;
//最大连接数量
private const int maxConnected = 4;
//记载所有连接的用户
private static List<ClientSocket> _clients = new List<ClientSocket>();
public static List<ClientSocket> clients { get { return _clients; } }
//全局唯一性
private void Awake()
{
if (instance != null)
{
Debug.Log("严重 : ServerCore已经存在!");
DestroyImmediate(gameObject);
}else
{
DontDestroyOnLoad(gameObject);
instance = this;
}
}
// Use this for initialization
void Start () {
instance = this;
//开启服务器主线程
serverThread = new Thread(new ThreadStart(StartServer));
serverThread.IsBackground = true; //设为后台线程,伴随主线程关闭而关闭
serverThread.Start();
}
//服务器主线程
void StartServer()
{
listener = new TcpListener(IPAddress.Parse(NetworkValue.ip), NetworkValue.port);
Debug.Log("服务器已开启: ip-" + NetworkValue.ip + " port-" + NetworkValue.port);
listener.Start();
//侦测连接的客户端
while (true)
{
TcpClient tcpclient = listener.AcceptTcpClient();//已连接的客户端,阻塞方法
Debug.Log("一个新用户! Client : " + tcpclient.Client.RemoteEndPoint);
if (_clients.Count < maxConnected)
{
//建立玩家连接类(开启每一个玩家的单独线程)
ClientSocket client = new ClientSocket(tcpclient);
_clients.Add(client);
}else
{
//向该用户发送"已满"
Thread.Sleep(500); //暂停线程500ms
tcpclient.Close();
}
}
}
//防止程序没有正确退出
void OnApplicationQuit()
{
if (serverThread != null && serverThread.IsAlive)
{
serverThread.Abort();
//serverThread.Join();
Debug.Log("serverThread :"+ serverThread.IsAlive);
}
if (listener != null)
{
listener.Stop();
}
//关闭所有用户的socket和线程
foreach (ClientSocket user in _clients)
{
if (user != null) user.Close();
}
}
void OnDestroy()
{
Debug.Log("server OnDestroy");
OnApplicationQuit();
}
//Client接收发送类
public class ClientSocket
{
//建立的通讯
private TcpClient client;
//stream流
private NetworkStream stream;
//socket是否处于活动中
private volatile bool __connected = false;
public bool connected { get { return __connected; } }
//接受队列
public Queue<string> recvQueue = new Queue<string>();
//发送队列
public Queue<string> sendQueue = new Queue<string>();
//缓存区大小
private int maxBufferSize = 4096;
//线程
public Thread clientThread = null;
//是否停止线程
private volatile bool stop = false;
//构造函数
public ClientSocket(TcpClient _client)
{
client = _client;
stream = client.GetStream();
//stop = false;
//开启线程
clientThread = new Thread(new ThreadStart(StartClient));
clientThread.IsBackground = true;
clientThread.Start();
}
//socket连接是否有效
bool IsOpen()
{
return !((client.Client.Poll(1000, SelectMode.SelectRead) && (client.Client.Available == 0)) || !client.Client.Connected);
}
//Client线程
void StartClient()
{
byte[] recvBuf = new byte[maxBufferSize];
while (!stop)
{
//连接是否有效
__connected = IsOpen();
//检查发送队列
if (sendQueue.Count > 0 && __connected)
{
byte[] buffer = Encoding.UTF8.GetBytes(sendQueue.Dequeue());
stream.Write(buffer, 0, buffer.Length);
stream.Flush();
}
//检查流接受数据
if (stream.DataAvailable && __connected)
{
int bytesRead = stream.Read(recvBuf, 0, maxBufferSize); //从流中获取数据,阻塞方法(如果没有数据,将阻塞线程)
if (bytesRead > 0)
{
string message = Encoding.UTF8.GetString(recvBuf);
Debug.Log("收到客户端消息:" + message);
recvQueue.Enqueue(message);
}
}
//线程暂停时间(毫秒)
Thread.Sleep(10);
}
//Close();
}
//添加消息到发送队列(外部方法)
public void Send(string message)
{
sendQueue.Enqueue(message);
}
//获取一条消息(外部方法)
public string Recv()
{
if (recvQueue.Count <= 0)
{
return null;
}
return recvQueue.Dequeue();
}
//关闭用户线程和socket连接
public void Close()
{
stop = true;
stream.Close();
client.Close();
if (clientThread != null && clientThread.IsAlive)
{
clientThread.Abort();
// 如果没有正确关闭线程,这里的Join就会阻塞,就会卡死编辑器
//sendThread.Join();
Debug.Log("server-clientThread: " + clientThread.IsAlive);
}
}
}
}
配置脚本:
public class NetworkValue {
//连接地址
private static string _ip = "192.168.1.100";
//端口号
private static int _port = 1234;
public static string ip
{
get
{
return _ip;
}
set
{
_ip = value;
}
}
public static int port
{
get
{
return _port;
}
set
{
_port = value;
}
}
}