上次的Socket服务器端只是开胃菜,这次我们把上次的代码进行完善和追加。
窗体如下
我根据读到的资料,对代码进行了重写
并对源码进行了大量的注释,希望大家能够读懂
public partial class Form1 : Form { public Form1() { InitializeComponent(); } //代理委托 delegate void FlushSocket(); //所有代理Socket的集合 List<Socket> AgentSocketList = new List<Socket>(); private void btnOpen_Click(object sender, EventArgs e) { //创建一个Socket对象 Socket severSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //绑定端口和IP IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text)); severSocket.Bind(endPoint); //开始监听 severSocket.Listen(10); //用别的线程来连接客户端 ThreadPool.QueueUserWorkItem(new WaitCallback(CallBackSocket), severSocket); } //回调函数 public void CallBackSocket(object obj) { //将参数obj强转成Socket类型 Socket severSocket = (Socket)obj; //开始连接 //主线程会在这里一直阻塞,直到连接到一个客户端 //返回值是一个代理通信Socket对象 //可能连接多个客户端,需要循环 while (true) { Socket socket = severSocket.Accept(); //往集合中添加代理Socket AgentSocketList.Add(socket); //解决跨线程访问控件问题 if (this.txtLog.InvokeRequired) { //FlushSocket fs = new FlushSocket(CallBackSocket); txtLog.Invoke(new FlushSocket(() => { FlushMsg(socket); })); } else { FlushMsg(socket); } } } //显示连接接收情况 public void FlushMsg(Socket socket) { txtLog.Text = "已成功连接:" + socket.RemoteEndPoint + "\r\n" + this.txtLog.Text; //接收数据 ThreadPool.QueueUserWorkItem(new WaitCallback(RecMsgFromClient), socket); } //接收数据 public void RecMsgFromClient(object obj) { Socket socket = (Socket)obj; //1M的缓存区 byte[] recByte = new byte[1024 * 1024]; while (true) { //将接收到的数据,存到缓存区 //因为Receive方法会阻塞线程,所以也需要用另一个线程来等待 int count = socket.Receive(recByte, 0, recByte.Length, SocketFlags.None); //对方退出了 if (count <= 0) { if (this.txtLog.InvokeRequired) { txtLog.Invoke(new FlushSocket(() => { txtLog.Text = string.Format("来自客户端{0}的消息;对方退出了\r\n{1}", socket.RemoteEndPoint, txtLog.Text); })); } else { //给接收文本框赋值 txtLog.Text = string.Format("来自客户端{0}的消息;对方退出了\r\n{1}", socket.RemoteEndPoint, txtLog.Text); } //关闭代理Socket socket.Shutdown(SocketShutdown.Both); socket.Close(); AgentSocketList.Remove(socket); return; } //将缓存区中的数据转成字符串 string str = Encoding.Default.GetString(recByte, 0, count); if (this.txtLog.InvokeRequired) { txtLog.Invoke(new FlushSocket(() => { txtLog.Text = string.Format("来自客户端{0}的内容;{1}\r\n{2}", socket.RemoteEndPoint, str, txtLog.Text); })); } else { //给接收文本框赋值 txtLog.Text = string.Format("来自客户端{0}的内容;{1}\r\n{2}", socket.RemoteEndPoint, str, txtLog.Text); } } } //向客户端发送消息 private void btnSend_Click(object sender, EventArgs e) { //遍历每一个代理Socket foreach (var socket in AgentSocketList) { //如果保持连接,就传输数据 if (socket.Connected) { byte[] myBuffer = Encoding.Default.GetBytes(txtSend.Text); socket.Send(myBuffer,0,myBuffer.Length,SocketFlags.None); } } } }
下面是显示效果
右边的是客户端,大家可以先不用在意,后面我会写客户端的,这里是用的别人的来检验服务器端。
我使用了“123”来进行发送和接收,都没问题,暂没有发现bug
时间: 2024-10-05 08:16:59