c# Winform socket通讯 实现单服务器到多个客户端的程序

2 篇文章 0 订阅

经过上次的socket 通讯demo   未加入多线程的应用

https://blog.csdn.net/dongnihao/article/details/83989561( 上次的demo)

那么这次我们通过加入multithreading多线程来实现多个客户端给服务器发消息。

 首先看服务器端的代码:

董厂长的服务器端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace 客户端czbk
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

      
        Socket socketSend;

        private void btnStart_Click(object sender, EventArgs e)
        {


                 //当点击开始监听的时候 在服务器端创建一个负责监听IP地址和端口号的Socket
         Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           //获取ip地址第一个参数是指定socket对象使用的寻址方案,即IPV4或IPV6;
           //第二个参数socket对象的套接字的类型,此处stream是表示流式套接字
           //第三个参数socket对象支持的协议,TCP协议或UDP协议。
         IPAddress ipaddress = IPAddress.Parse(txtIp.Text.Trim()); //获取文本框输入的IP地址
         //将IP地址和端口号绑定到网络节点endpoint上 
         IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(txtPort.Text.Trim())); //获取文本框上输入的端口号
         //监听绑定的网络节点
              socketWatch.Bind(endpoint);// 端口号里也包含了本机的IP地址  使用了绑定
             
             socketWatch.Listen(10); 
            Addmessage("Listen successfully!!! ");
           //下面开启一个新线程
             Thread th = new Thread(Listen);
             th.IsBackground = true;
             th.Start(socketWatch);
        }

   //将远程连接的客户端ip地址 和 socket 存入集合 这个我有点感觉像map
       // Dictionary<string, string>是一个泛型
        //他本身有集合的功能有时t 候可以把它看成数组
          //他的结构是这样的:Dictionary<[key], [value]>
         //他的特点是存入对象是需要与[key]值一一对应的存入该泛型
        //通过某一个一定的[key]去找到对应的值   这边不好搞 我就不写了
        //等待客户端的连接 并穿件一个负责通信的socket
        Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();



        void Listen(object o)
        {//因为只能被线程执行 所以我要写object o  然后再转化类型
            Socket socketWatch = o as Socket;
             //等待连接   创建一个负责通讯的socket  做一个类型转换16091007
            while (true)
            {
                try
                {
                      socketSend = socketWatch.Accept();
                    //这个是负责和客户端通信的socket 
                      dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
                      comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString());
                    Addmessage(socketSend.RemoteEndPoint.ToString() + "." + "A User Link to the service");//remoteendpoint这个是拿到远程ip地址和端口号
                    //为什么写个循环呢 因为每个客户端和服务器都要重新创建一个新的连接 有几个客户端就有几个socket
                    // 用线程去运行 不要放在主线程里面 开启一个新线程
                    Thread th = new Thread(Receive);//开启一个新线程. 不停接受了客户端发送的消息
                    th.IsBackground = true;
                    th.Start(socketSend);
                }
                catch 
                {
                }
                }
               
            }

     

        void Receive(object o)
         {//因为只能被线程执行 所以我要写object o  然后再转化类型
            Socket socketSend = o as Socket;
            while (true)
            { //客户端连接成功  服务器应该接受客户端发来的消息
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 2];
                    int r = socketSend.Receive(buffer);//
                    if (r == 0)
                    {
                        break;
                    }
                    string str = Encoding.UTF8.GetString(buffer, 0, r);//从0开始 解码r个
                    Addmessage(socketSend.RemoteEndPoint + ":" + str);
                }
                catch 
                {      //不显示给用户  就算有异常
                }
            }
          }


        void Addmessage(String str)
        {
            txtlog.AppendText(str+"\r\n");

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            //就是说在加载过程中 程序不会去检查这个多线程的错误
        }

        private void txtlog_TextChanged(object sender, EventArgs e)
        {

        }

        private void txtIp_TextChanged(object sender, EventArgs e)
        {

        }


        //服务器给客户端发消息
        private void btnSend_Click(object sender, EventArgs e)
        {
            string str = txtMsg.Text;
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
            string ip = comboBox1.SelectedItem.ToString();
            dicSocket[ip].Send(buffer);

        }

        private void textBox5_TextChanged(object sender, EventArgs e)
        {

        }

        
    }
}

我们从服务器短的winform界面上看到,为了给不同的客户端发消息。我添加了一个combox下拉来选择。

再来看客户端的代码:

董厂长的客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace 服务器端czbk
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Socket socketSend;

        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                //创建负责通信的socket
                socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Parse(txtServer.Text);
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
                //获得要连接的远程服务器应用程序的ip地址和端口号
                socketSend.Connect(point);
                Addmessgae("Link Successfully ,welcome ! ");
                
                //可能卡死  所以要开启多线程  不停 接受服务端信息
                Thread th = new Thread(Receive);
                th.IsBackground = true;
                th.Start();
            }
            catch  
            {
            }
        }

        void Receive( )
        {//因为只能被线程执行 所以我要写object o  然后再转化类型ddddaawassda    
            while (true)
            {

                byte[] buffer = new byte[1024 * 1024 * 5];
                //实际接收带的字节数
                int r = socketSend.Receive(buffer);//
                if (r == 0)
                {
                    break;
                }
                string s = Encoding.UTF8.GetString(buffer, 0, r);//从0开始解码r个
                Addmessgae(socketSend.RemoteEndPoint + ":" + s);
            }
        }

        void Addmessgae(String str)
        {
            txtLog.AppendText(str + "\r\n");// z追加文本  然后换行

        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            String str = txtMsg.Text.Trim();
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
            socketSend.Send(buffer);
        }

        private void txtLog_TextChanged(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1 addnew = new Form1();
            addnew.Show();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

      

    
         
    }
}

客户端这边基本和服务器端相同的,这边另外加一个button来实现添加客户端。

 

需要详细注释或者成品论文,或者PPT的可以点这个链接:完整socket通讯及论文和PPT

另有c# winform 图书管理程序:图书管理系统(Mysql sever 2008带bak完整数据库备份)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董厂长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值