首先这里我们是使用了线程来开辟多个连接通道,将这些连接存到一个List里面,然后对这个容器里面所有的客户端发送消息达到广播的目的
首先我们创建一个Client类,主要用来处理我们的消息接收和发送
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();
}
/// <summary>
/// 接收客户端数据
/// </summary>
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);
}
}
/// <summary>
/// 给客户端发送消息
/// </summary>
/// <param name="message"></param>
public void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
/// <summary>
/// 获取当前客户端连接的状态false表示断开连接
/// </summary>
public bool Connected
{
get { return clientSocket.Connected; }
}
}
然后在我们的主方法里面写具体的连接操作
class Program {
//所有连接的客户端的容器
static List<Client> clientList = new List<Client>();
/// <summary>
/// 广播消息
/// </summary>
/// <param name="message"></param>
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);//开启一个Socket
tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.2.124"),7788));//绑定IP和端口号
tcpServer.Listen(100);//开启监听,最大等待数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);
}
}
}
然后在我们的Unity搭建三个UI面版,一个Input输入框,一个发送消息的Button按钮,还有一个显示服务器消息的Test文本框,类似下面这样的,当然这个是NGUI,使用UGUI也是一样的方法
然后我们就可以编写我们客户端的代码了
public class ChatManager : MonoBehaviour
{
public string ipaddress = "192.168.2.124";
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 = "";//消息容器
// Use this for initialization
void Start () {
ConnectToServer();
}
// Update is called once per frame
void Update () {
if (message != null && message != "")
{
chatLabel.text += "\n" + message;
message = "";//清空消息
}
}
/// <summary>
/// 连接到服务器
/// </summary>
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();
}
/// <summary>
/// 这个线程方法 用来循环接收消息
/// </summary>
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;
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message"></param>
void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
/// <summary>
/// 发送消息的按钮方法
/// </summary>
public void OnSendButtonClick()
{
string value = textInput.value;//获取输入框的值
SendMessage(value);
textInput.value = "";
}
/// <summary>
/// 关闭连接
/// </summary>
void OnDestroy()
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();//关闭连接
}
}
这样将我们的工程build出来多开启几个客户端就可以看到广播的效果了