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

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

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

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

 

第一部分  窗体设计

1.服务器端

                                  

2.客户端

                                   

 

第二部分  代码

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

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值