服务器开启后肯定是等待多个客户端连接,这里使用一个死循环让服务器一直处于等待别客户端连接的状态,然后每连接一个客户端就开启一个线程接收客户端发来的消息然后广播给每个客户端。
首先是服务端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace MySever
{
class ClientSocket
{
private Socket m_ClientSocket;//当前连接服务器的客户端作用Sockets
private byte[] _buffer = new byte[1024];//开辟一段缓存空间
public ClientSocket(Socket socket)//构造函数,每次实例化就执行函数里面的代码
{
m_ClientSocket = socket;
Thread t = new Thread(RecieveMessage);//每当连接一个客户端就开始一个线程进行消息的接收
t.Start();
}
/// <summary>
/// 接收客户端消息
/// </summary>
public void RecieveMessage()
{
while (true)//使用死循环一直接收消息
{
if (m_ClientSocket.Poll(10, SelectMode.SelectRead))//判断客户端是否还在连接,True是没有连接,False表示还在连接
{
m_ClientSocket.Shutdown(SocketShutdown.Receive);
m_ClientSocket.Close();
break;
}
int lenght = m_ClientSocket.Receive(_buffer);
string message = Encoding.UTF8.GetString(_buffer, 0, lenght);
Console.WriteLine("接受到消息: " + message + "---来自:" + m_ClientSocket.LocalEndPoint);
Program.BroadcastMessage(message);//接收到一个客户端的消息后广播到所有的客户端
}
}
/// <summary>
/// 向客户端发送消息
/// </summary>
/// <param name="message"></param>
public void SendMessage(string message)
{
m_ClientSocket.Send(Encoding.UTF8.GetBytes(message));
}
/// <summary>
/// 客户端是否连接
/// </summary>
public bool Connected
{
get { return m_ClientSocket.Connected; }
}
}
}
这里创建了一个新的类ClientSocket用来管理所有连接的客户端并进行消息的发送和接收,同样使用死循环一直接收消息
下面是开启服务器和广播消息的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;//引用命名空间
using System.Net;
using System.Threading;
namespace MySever
{
class Program
{
public static List<ClientSocket> ClientSocketList = new List<ClientSocket>();
static void Main(string[] args)
{
Socket severSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
severSocket.Bind(new IPEndPoint(IPAddress.Parse("192.168.x.xxx"), 1314));
severSocket.Listen(100);
Console.WriteLine("服务器已经启动");
while(true)//表示一直接收客户端,每接收一个客户端暂停住等待下一个客户端连接
{
Socket socket = severSocket.Accept();
Console.WriteLine(socket.LocalEndPoint + " :已经连接");
ClientSocket clientSocket = new ClientSocket(socket);//实例化一个控制客户端的ClietSocket,在ClientSocket的构造函数里面进行数据的控制
ClientSocketList.Add(clientSocket);//每连接一个客户端,就加入到集合
}
}
/// <summary>
/// 消息的广播,发布到每个客户端
/// </summary>
/// <param name="message"></param>
public static void BroadcastMessage(string message)
{
List<ClientSocket> breakConnect = new List<ClientSocket>();//表示断开连接的客户端
foreach (var item in ClientSocketList)//遍历所有连接了服务器的客户端
{
if (item.Connected)//如果客户端还在连接
{
item.SendMessage(message);//就向客户端发送消息
}
else
{
breakConnect.Add(item);//否则就加入到断开连接的集合里
}
}
foreach (var item in breakConnect)//遍历断开连接的客户端
{
ClientSocketList.Remove(item);//从连接的客户端里移除断开连接的客户端
}
}
}
}
代码注释很清楚,每连接一个客户端就添加到已经连接的客户端集合里面,遍历所有连接的客户端分别向每个客户端发送消息,并且判断客户端的连接状态,从集合移除没有连接的客户端。到此服务器搭建已经完成,下面是客户端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace Client
{
class Program
{
private static byte[] _buffer = new byte[1024];
private static Socket socket;
static void Main(string[] args)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdress = IPAddress.Parse("192.168.x.xxx");//获取需要连接的服务器地址(使用本机地址)
IPEndPoint ipEndPoint = new IPEndPoint(ipAdress, 1314);//获取终结点和服务器的一致
socket.Connect(ipEndPoint);//连接服务器
Console.WriteLine("连接服务器成功...");
Thread t = new Thread(RecieveMessage);//开启一条线程进行来自服务器消息的接收
t.Start();
while (true)//可以循环向服务器发送消息
{
string input = Console.ReadLine();
SendMessage(input);
}
}
/// <summary>
/// 向服务器发送消息
/// </summary>
/// <param name="message"></param>
public static void SendMessage(string message)
{
socket.Send(Encoding.UTF8.GetBytes(message));
}
/// <summary>
/// 接收来自服务器的消息
/// </summary>
public static void RecieveMessage()
{
while (true)
{
int length = socket.Receive(_buffer);
string message = Encoding.UTF8.GetString(_buffer, 0, length);
Console.WriteLine("来自服务器的广播消息: " + message + "---" + socket.LocalEndPoint + "发送");
}
}
}
}
这里使用死循环可以重复发送消息和接收消息,连接服务器同样开启一个线程进行消息的接收,我们来看看效果。
首先开启服务器等待客户端连接:
开启第一个客户端:
开启第二个客户端:
由于我这个是同一台电脑进行的操作,所以客户端地址是一样的。
下面从一个客户端发送一条消息:
从第二个客户端发送消息:
到此一个最简单基础的多人连接的功能就已经完成了,后面将在Unity使用这个结构制作一个简易的多人聊天室。
欢迎加群:4364930讨论。