Socket服务器端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SocketServer
{
class Program
{
//服务器商所有客户端列表
public static List<Client> users = new List<Client>();
static void Main(string[] args)
{
new Server();
}
}
//服务器类
class Server
{
//声明socket对象
private Socket socket;
public Server()
{
//第一步,建立Socket对象(ipv4,数据流形式,TCP协议)
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//转化IP地址
IPAddress ipadress = IPAddress.Parse("0.0.0.0");
//绑定端口,提供服务
socket.Bind(new IPEndPoint(ipadress, 9999));
try
{
//开始监听
socket.Listen(60);
Console.WriteLine("服务器启动成功");
}catch(Exception ex)
{
Console.WriteLine("服务器启动失败"+ex.Message);
}
//开始循环等待用户连接
while (true)
{
//接受客户端连接
Socket client = socket.Accept();
//将新客户端对象,存储到列表中
Program.users.Add(new Client(client));
Console.WriteLine("有客户端连接了"+client.RemoteEndPoint.ToString());
//构建消息主体
byte[] msgBody = Encoding.UTF8.GetBytes("欢迎来到聊天室,请文明礼貌用语!");
//构建消息整体
byte[] msgByte = new byte[4 + 4 + msgBody.Length];
//消息标识字节数组
byte[] idbytes = BitConverter.GetBytes(2);
//消息长度字节数组
byte[] lenbytes = BitConverter.GetBytes(msgBody.Length);
//复制字节到指定数组
Array.Copy(idbytes, msgByte, 4);
//从指定数组指定位置,复制到另一数组指定位置,指定长度
Array.Copy(lenbytes, 0, msgByte, 4, lenbytes.Length);
Array.Copy(msgBody, 0, msgByte, 8, msgBody.Length);
//向客户端发送消息
client.Send(msgByte);
//断开连接
//socket.Close();
}
}
}
class Client
{
/// <summary>
/// 连接
/// </summary>
private Socket socket;
/// <summary>
/// 线程
/// </summary>
private Thread thread;
private byte[] buffers = new byte[2048];
public Client(Socket sk)
{
this.socket = sk;
//添加线程,处理消息接收
thread = new Thread(ReceiveData);
thread.IsBackground = true;
//启动线程
thread.Start();
}
private void ReceiveData()
{
while (true)
{
try
{
//将收到数据,存在在缓存里,并获取长度len
int len = socket.Receive(buffers);
if (len > 8)
{
//解析标识
byte[] idbytes = new byte[4];
Array.Copy(buffers, 0, idbytes, 0, 4);
//还原消息标识
int msgId = BitConverter.ToInt32(idbytes, 0);
//消息长度
byte[] lenbytes = new byte[4];
Array.Copy(buffers, 4, lenbytes, 0, 4);
//还原消息长度
int msgLen = BitConverter.ToInt32(lenbytes, 0);
//消息主体
byte[] bodybytes = new byte[msgLen];
Array.Copy(buffers, 8, bodybytes, 0, msgLen);
//将消息主体还原成字符串
string msgBody = Encoding.UTF8.GetString(bodybytes);
//控制台输出
Console.WriteLine("id={0},len={1},body={2}", msgId, msgLen, msgBody);
switch (msgId)
{
case 1: //公聊消息
//获取收到的整个消息字节数组
byte[] tmpbytes = new byte[4 + 4 + msgLen];
Array.Copy(buffers, tmpbytes, tmpbytes.Length);
//遍历用户,进行转发
foreach (Client item in Program.users)
{
item.Send(tmpbytes);
}
break;
}
}
/* //还原收到的内容
string msg = Encoding.UTF8.GetString(buffers, 0, len);
//将这个消息发送给所有客户端
foreach (Client item in Program.users)
{
//发送消息
item.Send(msg);
}
Console.WriteLine(Encoding.UTF8.GetString(buffers, 0, len));
*/
}
catch (Exception ex)
{
Console.WriteLine("客户端" + socket.RemoteEndPoint.ToString() + "掉线了");
//掉线后,把自己从列表中删除掉
Program.users.Remove(this);
//关闭连接
socket.Close();
//关闭线程
thread.Abort();
}
}
}
/// <summary>
/// 发送消息方法
/// </summary>
/// <param name="msg"></param>
public void Send(string msg)
{
socket.Send(Encoding.UTF8.GetBytes(msg));
}
/// <summary>
/// 发送字节数组
/// </summary>
/// <param name="bytes"></param>
public void Send(byte[] bytes)
{
socket.Send(bytes);
}
}
}
客户端代码
/*
*Copyright(C) 2015 by #COMPANY#
*All rights reserved.
*FileName: #SCRIPTFULLNAME#
*Author: #AUTHOR#
*Version: #VERSION#
*UnityVersion:#UNITYVERSION#
*Date: #DATE#
*/
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using UnityEngine.UI;
using System;
public class ChatRoom : MonoBehaviour {
private Socket socket;
//定义缓存数组长度
private byte[] buffers = new byte[2048];
//开启线程,用来处理数据接收
private Thread thread;
//接收到的消息对象
public struct MsgData
{
public int id;
public string msg;
}
//消息队列
public Queue<MsgData> msgQueue = new Queue<MsgData>();
//消息文本框
public Msg txtMsg;
//消息发送文本和按钮
public InputField inputMsg;
public Button btnSend;
// Use this for initialization
void Start()
{
//获取消息文本框
txtMsg = this.transform.Find("msg").GetComponent<Msg>();
inputMsg = this.transform.Find("input").GetComponent<InputField>();
btnSend = this.transform.Find("btnSend").GetComponent<Button>();
//按钮点击 ,发送消息
btnSend.onClick.AddListener(delegate () {
//构建消息主体
byte[] msgBody = Encoding.UTF8.GetBytes(inputMsg.text.Trim());
//构建消息整体
byte[] msgByte = new byte[4 + 4 + msgBody.Length];
//消息标识字节数组
byte[] idbytes = BitConverter.GetBytes(1);
//消息长度字节数组
byte[] lenbytes = BitConverter.GetBytes(msgBody.Length);
//复制字节到指定数组
Array.Copy(idbytes, msgByte, 4);
//从指定数组指定位置,复制到另一数组指定位置,指定长度
Array.Copy(lenbytes, 0, msgByte, 4, lenbytes.Length);
Array.Copy(msgBody, 0, msgByte, 8, msgBody.Length);
//发送
socket.Send(msgByte);
//清空输入框
inputMsg.text = "";
});
//创建Socket对象
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//连接服务器
socket.Connect("172.18.32.106", 9999);
if (socket.Connected)
{
print("连接服务器成功!");
//创建线程,用于处理消息接收
thread = new Thread(ReceiveData);
//设置为后台线程
thread.IsBackground = true;
//启动
thread.Start();
}
else
{
print("连接失败!");
}
}
private void ReceiveData()
{
while (true)
{
//接收数据,将收到的数据存储在buffers里,数据的长度为len
int len = socket.Receive(buffers);
if (len > 8)
{
//解析标识
byte[] idbytes = new byte[4];
Array.Copy(buffers, 0, idbytes, 0, 4);
//还原消息标识
int msgId = BitConverter.ToInt32(idbytes, 0);
//消息长度
byte[] lenbytes = new byte[4];
Array.Copy(buffers, 4, lenbytes, 0, 4);
//还原消息长度
int msgLen = BitConverter.ToInt32(lenbytes, 0);
//消息主体
byte[] bodybytes = new byte[msgLen];
Array.Copy(buffers, 8, bodybytes, 0, msgLen);
//将消息主体还原成字符串
string msgBody = Encoding.UTF8.GetString(bodybytes);
//将消息存储为结构体,包括 id,msgbody
MsgData md = new MsgData();
md.id = msgId;
md.msg = msgBody;
//把收到的消息对象,存储到队列
msgQueue.Enqueue(md);
}
}
}
// Update is called once per frame
void Update()
{
while (msgQueue.Count > 0)
{
//从头取出消息结构体
MsgData data = msgQueue.Dequeue();
switch (data.id)
{
case 1: //公聊消息
txtMsg.AddMsg(data.msg);
break;
case 2://系统消息
txtMsg.AddMsg("<color=#ff0000>" + data.msg + "</color>");
break;
}
}
}
private void OnDestroy()
{
//关闭连接
socket.Close();
//停止线程
thread.Abort();
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text;
public class Msg : MonoBehaviour {
private Text txt;
private StringBuilder sb = new StringBuilder();
void Start () {
txt = this.transform.Find("Text").GetComponent<Text>();
}
/// <summary>
/// 向文本框中添加内容
/// </summary>
/// <param name="msg"></param>
public void AddMsg(string msg)
{
//累计消息
sb.Append(msg + "\n");
//文本显示内容
txt.text = sb.ToString();
}
}