实现了简单的聊天室功能,多个客户端连接一个服务器,客户端和服务器双向收发消息,服务器向所有用户广播消息
服务器:
主函数文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SeverTest { class Program { static void Main(string[] args) { SeverControl sever = new SeverControl(); sever.start(); Console.ReadLine(); } } }
SeverControl类文件
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SeverTest { class SeverControl { private Socket severSocket; private List<Socket> clientList;//创建一个socket集合来保存正在连接的客户端 public SeverControl() { severSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); clientList = new List<Socket>(); } public void start() { severSocket.Bind(new IPEndPoint(IPAddress.Any,12581));//设置允许访问ip和端口 severSocket.Listen(10);//开始监听端口 Console.WriteLine("服务器启动"); Thread acceptThread = new Thread(Accept);//新建一个线程来接受客户端连接 acceptThread.IsBackground = true; acceptThread.Start(); } public void Accept() { Socket client = severSocket.Accept(); IPEndPoint point = client.RemoteEndPoint as IPEndPoint;//RemoteEndPoint必须强制转成IPEndPoint Console.WriteLine(point.Address + "[" + point.Port + "]" + " 连接成功"); clientList.Add(client);//将连接保存到集合 Thread receiveThread = new Thread(Receive);//新建一个线程来接收客户端传来的数据 receiveThread.IsBackground = true; receiveThread.Start(client); Accept(); } public void Receive(Object obj)//带参数线程函数形传参必须是Object { byte[] s = new byte[1024]; Socket client = obj as Socket; IPEndPoint point = client.RemoteEndPoint as IPEndPoint; //clint.receive方法会挂起线程,当客户端断开连接时会抛出异常 try { int msglen = client.Receive(s);//获得客户端传来的数据,以byte数组形式传给s,返回字符串长度 string str = point.Address + " 说: " + Encoding.UTF8.GetString(s, 0, msglen); Console.WriteLine(str); BroadCast(client, str);//向所有连接的客户端进行广播 Receive(client); } catch { Console.WriteLine(point.Address+"["+point.Port+"]"+"断开"); clientList.Remove(client);//将连接从集合移除 } } private void BroadCast(Socket clientother,string str) { foreach(var client in clientList) { if (client == clientother) { //本人发出,不回应 } else { client.Send(Encoding.UTF8.GetBytes(str)); } } } } }
客户端
主函数文件
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace ClientTest { class Program { static void Main(string[] args) { ClientControl client = new ClientControl(); client.connect("127.0.0.1",12581); client.send(); } } }
ClientControl类文件
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ClientTest { public class ClientControl { private Socket clientSocket; public ClientControl() { clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); } public void connect(string ip,int port) { clientSocket.Connect(ip,port); Console.WriteLine("连接服务器成功"); Console.WriteLine("输入任意字符聊天,输入quit退出"); Thread receiveThread = new Thread(Receive); receiveThread.IsBackground = true; receiveThread.Start(); } private void Receive() { byte[] s = new byte[1024]; try { int msglen = clientSocket.Receive(s); Console.WriteLine(Encoding.UTF8.GetString(s, 0, msglen)); Receive(); } catch { Console.WriteLine("服务器关闭"); } } public void send() { Thread srThread = new Thread(SendAndRead); srThread.Start(); } private void SendAndRead() { string s = Console.ReadLine(); while (s != "quit") { clientSocket.Send(Encoding.UTF8.GetBytes(s)); s = Console.ReadLine(); } } } }
注:本示例运行时需分开放在两个项目中运行