上面我们创建了tcp的客户端和服务端,但是只能进行消息的一次收发。这次我们做一个unity的简易聊天室,使用了线程,可以使用多个客户端连接服务器,并且一个客户端给服务器发消息后,服务器会将消息群发给所有客户端。
服务器端分为Program和Client,在Program中进行Ip和端口的绑定并与客户端建立连接,消息的接收和发送放在Client中、
服务端之Program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;
namespace _022_聊天室_socket_tcp服务器端 {
class Program {
static List<Client> clientList = new List<Client>();
// 广播消息
public static void BroadcastMessage(string message)
{
var notConnectedList = new List<Client>();
foreach (var client in clientList)
{
if (client.Connected)
client.SendMessage(message);
else
{
notConnectedList.Add(client);
}
}
foreach (var temp in notConnectedList)
{
clientList.Remove(temp);
}
}
static void Main(string[] args) {
Socket tcpServer = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.101"),7788));
tcpServer.Listen(100);
Console.WriteLine("server running...");
while (true)
{
Socket clientSocket = tcpServer.Accept();
Console.WriteLine("a client is connected !");
Client client = new Client(clientSocket);//把与每个客户端通信的逻辑(收发消息)放到client类里面进行处理
clientList.Add(client);
}
}
}
}
服务端之Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace _022_聊天室_socket_tcp服务器端 {
// 用来跟客户端做通信
class Client
{
private Socket clientSocket;
private Thread t;
private byte[] data = new byte[1024];//这个是一个数据容器
public Client(Socket s)
{
clientSocket = s;
//启动一个线程 处理客户端的数据接收
t = new Thread(ReceiveMessage);
t.Start();
}
// 接收数据
private void ReceiveMessage()
{
//一直接收客户端的数据
while (true)
{
//在接收数据之前 判断一下socket连接是否断开
if (clientSocket.Poll(10, SelectMode.SelectRead))
{
clientSocket.Close();
break;//跳出循环 终止线程的执行
}
int length = clientSocket.Receive(data);
string message = Encoding.UTF8.GetString(data, 0, length);
//接收到数据的时候 要把这个数据 分发到客户端
//广播这个消息
Program.BroadcastMessage(message);
Console.WriteLine("收到了消息:"+message);
}
}
// 发送消息
public void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
// 判断是否连接
public bool Connected
{
get { return clientSocket.Connected; }
}
}
}
客户端:因为是基于unity的聊天室,所以首先创建简单的UI界面
代码:
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class ChatManager : MonoBehaviour
{
public string ipaddress = "192.168.1.101";
public int port = 7788;
public UIInput textInput;
public UILabel chatLabel;
private Socket clientSocket;
private Thread t;
private byte[] data = new byte[1024];//数据容器
private string message = "";//消息容器
void Start () {
ConnectToServer();
}
void Update () {
if (message != null && message != "")
{
chatLabel.text += "\n" + message;
message = "";//清空消息
}
}
void ConnectToServer()
{
clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
//跟服务器端建立连接
clientSocket.Connect( new IPEndPoint(IPAddress.Parse(ipaddress),port) );
//创建一个新的线程 用来接收消息
t = new Thread(ReceiveMessage);
t.Start();
}
// 这个线程方法 用来循环接收消息
void ReceiveMessage()
{
while (true)
{
if (clientSocket.Connected == false)
break;
int length = clientSocket.Receive(data);
message = Encoding.UTF8.GetString(data, 0, length);
//chatLabel.text += "\n" + message;
}
}
// 发送消息
void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
// 发送按钮点击
public void OnSendButtonClick()
{
string value = textInput.value;
SendMessage(value);
textInput.value = "";
}
void OnDestroy()
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();//关闭连接
}
}