欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C# Sockets实现服务器与多个客户端进行通讯

程序员文章站 2022-05-19 14:09:19
...

        学习一个新的东西,首先要知道其原理,对于Sockets的学习,可先看一下文档:  

        http://blog.csdn.net/hulihui/article/details/3230503#st      点击打开链接        PS: /*附有源码*/

        刚开始是写代码实现了一个客户端和服务器的通讯,后来完善代码,实现了多个客户端与服务器端的通讯,由于原理是差不多的,这里就直接介绍多个客户端与服务器进行通讯。

 

第一部分  窗体设计

1.服务器端

                                  C# Sockets实现服务器与多个客户端进行通讯

2.客户端

                                   C# Sockets实现服务器与多个客户端进行通讯

 

第二部分  代码

1.服务器端:

– 申请一个socket (socketWatch)用来监听的
– 绑定到一个IP地址和一个端口上
– 开启侦听,等待接授客户端的连接
– 当有连接时创建一个用于和连接进来的客户端进行通信的socket(socketConnection)
– 即续监听,等侍下一个客户的连接

//服务器端
using System.IO;
using System.Net;
using System.Threading;
using System.Net.Sockets;
 

namespace SocketsServer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Socket socketWatch = null;
        Thread threadWatch = null;
 

        private void startconn_Click(object sender, EventArgs e)
        {
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ipaddress = IPAddress.Parse(localip.Text.Trim());
            IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(porttext.Text.Trim()));
            socketWatch.Bind(endpoint);
 
            socketWatch.Listen(10);
            threadWatch = new Thread(WatchingConn);
            threadWatch.IsBackground = true;
            threadWatch.Start();

            this.Invoke(new Action(() =>
            {
                recmsg.AppendText("开始对客户端进行监听!" + "\r\n");
            }
                ));
        }

  
        //保存了服务器端所有负责和客户端通信发套接字
        Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
        //保存了服务器端所有负责调用通信套接字.Receive方法的线程
        Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();

        //Socket socConn = null;

        private void WatchingConn(object obj)
        {
            while (true)
            {
                Socket socConn = socketWatch.Accept();

                this.Invoke(new Action(() => {
                    //向下拉项中添加一个客户端的ip端口字符串,作为客户端的唯一标识
                    iptext.Items.Add(socConn.RemoteEndPoint.ToString());
                }));

        
                ////将与客户端通信的套接字对象sokConn添加到键值对集合中,并以客户端IP端口作为键
                dictSocket.Add(socConn.RemoteEndPoint.ToString(), socConn);
  
                ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);

                Thread trd = new Thread(pts);
                trd.IsBackground = true;
                trd.Start(socConn);

                dictThread.Add(socConn.RemoteEndPoint.ToString(), trd);
                this.Invoke(new Action(()=>
                    {
                        recmsg.AppendText("客户端连接成功!" + "\r\n");
                    }
                    ));
            }
        }

 

        private void RecMsg(object socketClientPara)
        {
            Socket socketRec = socketClientPara as Socket;

            while (true)
            {
                byte[] arrRecMsg = new byte[1024 * 1024];

                //int length = socketClient.Receive(arrRecMsg);//......wrong...... 
                int length = -1;
                try
                {
                    length = socketRec.Receive(arrRecMsg);
                }
                catch (SocketException ex)
                {
                    MessageBox.Show("异常:" + ex.Message);
                    //从通信套接字集合中删除被中断连接的通信套接字对象
                    dictSocket.Remove(socketRec.RemoteEndPoint.ToString());
                    //从通信线程结合中删除被终端连接的通信线程对象
                    dictThread.Remove(socketRec.RemoteEndPoint.ToString());
                    //从列表中移除被中断的连接 ip:Port
                    iptext.Items.Remove(socketRec.RemoteEndPoint.ToString());
                    break;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("异常:" + ex.Message);
                    break;
                }
 
                string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                this.Invoke(new Action(() => {
                    recmsg.AppendText(iptext.Text + ":\r\n" + GetTime() + "\r\n" + str + "\r\n");

                }));

                Thread.Sleep(10);
            }
        }

 

        private DateTime GetTime()
        {

            DateTime getTime = new DateTime();
            getTime = DateTime.Now;
            return getTime;
        }

 
        private void SendMsg(string sendMsg)
        {
            if (string.IsNullOrEmpty(iptext.Text))
            {
                MessageBox.Show("请选择通信IP!");
            }
            else
            {
                byte[] strSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                string strClientKey = iptext.Text;//通过Key匹配对应ip地址的客户端
                dictSocket[strClientKey].Send(strSendMsg);
                this.Invoke(new Action(() =>
                {
                    recmsg.AppendText("服务器:" + "\r\n" + GetTime() + "\r\n" + sendMsg + "\r\n");

                }));

                sendmsg.Text = null;
            }
        }

 

        private void sendok_Click(object sender, EventArgs e)
        {
            SendMsg(sendmsg.Text.Trim());
        }
    }
}

2.客户端:

– 申请一个socket
– 连接服务器(指明IP地址和端口号)

//客户端
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
 

namespace SocketsClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

 
        Socket socketWatch = null;
        Thread threadWatch = null;
 

        private void startconn_Click(object sender, EventArgs e)
        {
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress address = IPAddress.Parse(iptext.Text.Trim());
            IPEndPoint endpoint = new IPEndPoint(address, int.Parse(porttext.Text.Trim()));

            socketWatch.Connect(endpoint);
           // socketWatch.Bind(endpoint);//...报错(服务器是Bind,客户端是Connect)...
            threadWatch = new Thread(RecMsg);
            threadWatch.IsBackground = true;
            threadWatch.Start();
        }

 

        private void RecMsg(object obj)
        {
            while (true)
            {
                byte[] arrRecMsg = new byte[1024 * 1024];
                int length = socketWatch.Receive(arrRecMsg);
                string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                this.Invoke(new Action(() => {
                    recmsg.AppendText("服务器:" + "\r\n" + GetTime() + "\r\n" + str + "\r\n");

                }));
            }
        }

 

        private DateTime GetTime()
        {
            DateTime getTime = new DateTime();
            getTime = DateTime.Now;
            return getTime;
        }
 

        private void SendMsg(string sendMsg)
        {
            byte[] strSenMsg = Encoding.UTF8.GetBytes(sendMsg);
            socketWatch.Send(strSenMsg); 

            this.Invoke(new Action(() =>
            {
                recmsg.AppendText("客户端:" + "\r\n" + GetTime() + "\r\n" + sendMsg + "\r\n");

            }));

            sendmsg.Text = null;
        }


        private void sendok_Click(object sender, EventArgs e)
        {
            SendMsg(sendmsg.Text.Trim());
        }
    }
}

下载路径:下载链接
 

————————————————
版权声明:本文为CSDN博主「勤劳的小码农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011602967/article/details/50728443

https://blog.csdn.net/u011602967/article/details/50728443