C#使用Socket实现一个socket服务器与多个socket客户端通信

2023-11-16

        在分布式调度系统中,如果要实现调度服务器与多台计算节点服务器之间通信,采用socket来实现是一种实现方式,当然我们也可以通过数据存储任务,子节点来完成任务,但是往往使用数据作为任务存储都需要定制开发,要维护数据库中任务记录状态等等。开发的东西还是有点多,而且还不够灵活。因此,我个人是比较偏向于使用socket来实现任务的调度工作。原因:使用socket实现调度比较灵活,而且扩展性都比较好。

  实现思路:调度服务器要实现调度工作,它必须与所有计算节点之间建立连接。而且他需要知道每台计算节点的任务状况,因此服务器节点必须存储与所有计算节点的socket连接对象。

  在客户端唯一需要知道的就是它归属的调度服务器的通信IP和端口,因此client是发送连接的主动方,由调度服务器监听是否有client请求建立连接,当建立连接成功后,把该连接信息存储到一个结合中以便监控client的存货状态及通信使用。

        扩展:

        由于server端是存储了所有server与client的连接对象,因此我们是可以基于此demo的基础上实现聊天系统:        每当一个与用户发言时,是由server接收到的某个用户的发言信息的,此时服务器端可以通过循环发送该用户发送的信息给每个已经连接连接的用户(排除发送者)。

Server端代码(Window Console Project):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;


 namespace SocketServerAcceptMultipleClient
 {
    public class SocketServer
     {
         // 创建一个和客户端通信的套接字
        static Socket socketwatch = null;
        //定义一个集合,存储客户端信息
         static Dictionary<string, Socket> clientConnectionItems = new Dictionary<string, Socket> { };
 
         public static void Main(string[] args)
         {
             //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)  
             socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
             //服务端发送信息需要一个IP地址和端口号  
             IPAddress address = IPAddress.Parse("127.0.0.1");
             //将IP地址和端口号绑定到网络节点point上  
             IPEndPoint point = new IPEndPoint(address, 8098);
             //此端口专门用来监听的  
 
             //监听绑定的网络节点  
             socketwatch.Bind(point); 
             //将套接字的监听队列长度限制为20  
             socketwatch.Listen(20);
             //负责监听客户端的线程:创建一个监听线程  
            Thread threadwatch = new Thread(watchconnecting);
             //将窗体线程设置为与后台同步,随着主线程结束而结束  
            threadwatch.IsBackground = true; 
             //启动线程     
             threadwatch.Start();
             Console.WriteLine("开启监听。。。");
            Console.WriteLine("点击输入任意数据回车退出程序。。。");
            Console.ReadKey();
             Console.WriteLine("退出监听,并关闭程序。");
         }

         //监听客户端发来的请求  
         static void watchconnecting()
         {
             Socket connection = null;
             //持续不断监听客户端发来的请求     
            while (true)
            {
                 try
                 {
                     connection = socketwatch.Accept();
                 }
                 catch (Exception ex)
                {
                     //提示套接字监听异常     
                     Console.WriteLine(ex.Message);
                     break;
               }
 
                 //获取客户端的IP和端口号  
                IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
                 int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port; 
                 //让客户显示"连接成功的"的信息  
                string sendmsg = "连接服务端成功!\r\n" + "本地IP:" + clientIP + ",本地端口" + clientPort.ToString();
                byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
                 connection.Send(arrSendMsg);
 
                 //客户端网络结点号  
                 string remoteEndPoint = connection.RemoteEndPoint.ToString();
                //显示与客户端连接情况
                Console.WriteLine("成功与" + remoteEndPoint + "客户端建立连接!\t\n");
                 //添加客户端信息  
                clientConnectionItems.Add(remoteEndPoint, connection);
                //IPEndPoint netpoint = new IPEndPoint(clientIP,clientPort); 
                 IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint;
                //创建一个通信线程      
                 ParameterizedThreadStart pts = new ParameterizedThreadStart(recv);
                 Thread thread = new Thread(pts);
                 //设置为后台线程,随着主线程退出而退出 
                thread.IsBackground = true;
                //启动线程     
                 thread.Start(connection);
            }
         }
 
         /// <summary>
         /// 接收客户端发来的信息,客户端套接字对象
       /// </summary>
       /// <param name="socketclientpara"></param>    
        static void recv(object socketclientpara)
        {
             Socket socketServer = socketclientpara as Socket; 
            while (true)
             {
                 //创建一个内存缓冲区,其大小为1024*1024字节  即1M     
                 byte[] arrServerRecMsg = new byte[1024 * 1024];
                 //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度    
                 try
                 {
                     int length = socketServer.Receive(arrServerRecMsg); 
                     //将机器接受到的字节数组转换为人可以读懂的字符串     
                     string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length); 
                     //将发送的字符串信息附加到文本框txtMsg上     
                    Console.WriteLine("客户端:" + socketServer.RemoteEndPoint + ",time:" + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n\n"); 
                     socketServer.Send(Encoding.UTF8.GetBytes("测试server 是否可以发送数据给client "));
                 }
                 catch (Exception ex)
                 {                          clientConnectionItems.Remove(socketServer.RemoteEndPoint.ToString()); 
                     Console.WriteLine("Client Count:" + clientConnectionItems.Count); 
                     //提示套接字监听异常  
                        Console.WriteLine("客户端" + socketServer.RemoteEndPoint + "已经中断连接" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace + "\r\n");
                     //关闭之前accept出来的和客户端进行通信的套接字 
                     socketServer.Close();
                     break;
                 }
             }
         }
 
         ///      
         /// 获取当前系统时间的方法    
         /// 当前时间     
         static DateTime GetCurrentTime()
         {
            DateTime currentTime = new DateTime();
             currentTime = DateTime.Now;
            return currentTime;
         }
     }
 }

 Client端代码(Window Form Project):

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.Threading;
 using System.Net.Sockets;
 using System.Net;
 using System.Diagnostics;
  
 namespace SocketClient
  {
      public partial class Main : Form
      {
          //创建 1个客户端套接字 和1个负责监听服务端请求的线程  
          Thread threadclient = null;
          Socket socketclient = null;
  
          public Main()
          {
              InitializeComponent();
  
              StartPosition = FormStartPosition.CenterScreen;
              //关闭对文本框的非法线程操作检查  
              TextBox.CheckForIllegalCrossThreadCalls = false;
  
              this.btnSendMessage.Enabled = false;
              this.btnSendMessage.Visible = false;
  
              this.txtMessage.Visible = false;
          }
  
          private void btnConnection_Click(object sender, EventArgs e)
          {
              this.btnConnection.Enabled = false;
              //定义一个套接字监听  
              socketclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  
              //获取文本框中的IP地址  
              IPAddress address = IPAddress.Parse("127.0.0.1");
  
              //将获取的IP地址和端口号绑定在网络节点上  
              IPEndPoint point = new IPEndPoint(address, 8098);
  
              try
              {
                  //客户端套接字连接到网络节点上,用的是Connect  
                  socketclient.Connect(point);
                  this.btnSendMessage.Enabled = true;
                  this.btnSendMessage.Visible = true;
                  this.txtMessage.Visible = true;
              }
              catch (Exception)
              {
                  Debug.WriteLine("连接失败\r\n");
  
                  this.txtDebugInfo.AppendText("连接失败\r\n");
                  return;
              }
  
              threadclient = new Thread(recv);
              threadclient.IsBackground = true;
              threadclient.Start();
          }
  
          // 接收服务端发来信息的方法    
          void recv()
          {
              int x = 0;
              //持续监听服务端发来的消息 
              while (true)
              {
                  try
                  {
                      //定义一个1M的内存缓冲区,用于临时性存储接收到的消息  
                      byte[] arrRecvmsg = new byte[1024 * 1024];
  
                      //将客户端套接字接收到的数据存入内存缓冲区,并获取长度  
                      int length = socketclient.Receive(arrRecvmsg);
  
                      //将套接字获取到的字符数组转换为人可以看懂的字符串  
                      string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length);
                      if (x == 1)
                      {
                          this.txtDebugInfo.AppendText("服务器:" + GetCurrentTime() + "\r\n" + strRevMsg + "\r\n\n");
                          Debug.WriteLine("服务器:" + GetCurrentTime() + "\r\n" + strRevMsg + "\r\n\n");
                      }
                      else
                      {
                          this.txtDebugInfo.AppendText(strRevMsg + "\r\n\n");
                          Debug.WriteLine(strRevMsg + "\r\n\n");
                          x = 1;
                      }
                  }
                  catch (Exception ex)
                  {
                     Debug.WriteLine("远程服务器已经中断连接" + "\r\n\n");
                     Debug.WriteLine("远程服务器已经中断连接" + "\r\n");
                     break;
                 }
             }
         }
 
         //获取当前系统时间  
         DateTime GetCurrentTime()
         {
             DateTime currentTime = new DateTime();
             currentTime = DateTime.Now;
             return currentTime;
         }
 
         //发送字符信息到服务端的方法  
         void ClientSendMsg(string sendMsg)
         {
             //将输入的内容字符串转换为机器可以识别的字节数组     
             byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
             //调用客户端套接字发送字节数组     
             socketclient.Send(arrClientSendMsg);
             //将发送的信息追加到聊天内容文本框中     
             Debug.WriteLine("hello...." + ": " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n\n");
             this.txtDebugInfo.AppendText("hello...." + ": " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n\n");
         }
 
         private void btnSendMessage_Click(object sender, EventArgs e)
         {
             //调用ClientSendMsg方法 将文本框中输入的信息发送给服务端     
             ClientSendMsg(this.txtMessage.Text.Trim());
             this.txtMessage.Clear();
         }
     }
 }

代码下载地址

 链接:http://pan.baidu.com/s/1kVBUOD5 密码:16ib

https://blog.csdn.net/guomei1345/article/details/80595163

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#使用Socket实现一个socket服务器与多个socket客户端通信 的相关文章

  • 在ubuntu下编译opencv程序后,执行报下面到错误: error while loading shared libraries: libopencv_core.so.2.4: cannot op

    转自 https www douban com note 327349156 在ubuntu下编译opencv程序后 执行报下面到错误 error while loading shared libraries libopencv core
  • 使用Python 进行分析

    在当今竞争激烈的互联网时代 对于网站的SEO优化至关重要 本文将介绍一种强大的秘密武器 使用Python 进行竞争对手网站分析 通过这种技术 您可以深入了解竞争对手的网站结构 关键词排名和优化策略 为您的SEO优化工作提供有力支持 1 为什
  • 神经网络随手记-1

    目录 sigmod函数主要缺点 Relu 线性整流函数 Leaky ReLU 随机梯度下降法 sigmod函数主要缺点 在输入值变大时 梯度会变得非常小甚至消失 这意味着 在训练神经网络时 如果发生这种饱和 我们将无法根据梯度来更新权重 函
  • 传感器尺寸与像素密度对相片分辨率的影响

    在人们日常生活摄影中 相机的传感器尺寸以及像素素往往决定了一幅图像的清晰度 当然 不同的镜头 不同的CMOS质量等等都会对相片的质量产生影响 今天就简单讨论讨论传感器尺寸和像素密度对图像分辨率的影响 当传感器尺寸一定时 像素越多 也就是像素
  • Python-集合

    探索Python集合的奇妙世界 在Python编程中 集合 Set 是一种强大且有用的数据结构 它用于存储多个不重复的元素 集合的独特之处在于它的元素是无序的 并且每个元素都是唯一的 这使得集合在处理去重和进行快速成员检查时非常有效 创建集
  • 手把手带你打造自己的UI样式库(第五章)之常用页面切图的设计与开发

    常用页面切图的设计与开发 在一些大的前端团队中 前端工程师这个职位会出现一个分支 叫做重构工程师 重构工程师主要负责 HTML 和 CSS 的制作 也就是把设计稿转换成 HTML 和 CSS 代码 重构工作完成以后 把制作好的 HTML 和

随机推荐

  • 【第十四届蓝桥杯单片机组底层驱动测试】

    第十四届蓝桥杯单片机组底层驱动测试 下面分享的是第十四届蓝桥杯单片机组底层驱动代码的测试和相关说明 今年官方提供的资料包中底层驱动代码和以往有了变化 主要代码还是提供给了我们 只是此次没有了相关头文件iic h ds1302 onewire
  • win10剪贴板快捷键win+v

    win v可以出现最近10多次粘贴的数据
  • Ioc容器refresh总结(3)--- Spring源码从入门到精通(三十三)

    上篇文章介绍了 调用bean工厂的后置处理器 主要分为两步 他是在beanFactory预准备标准初始化之后执行invokBeanFactoryPostProcessor 先调用beanDefinitionRegistryPostProce
  • [paper] MTCNN

    MTCNN 论文全称 Joint Face Detection and Alignment using Multi task Cascaded Convolutional Networks 论文下载链接 https arxiv org ab
  • vue.js基础学习(模板语法)

    基础入门 vue js模板语法 1 模板语法 methods 给vue定义方法 this 指向当前vue实例 v html 让内容以HTML形式编译 v bind 绑定动态数据 v noce 当数据发生改变时 插值处内容不发生改变 动态属性
  • maven相关

    1 webxml attribute is required or pre existing WEB INF web xml if executing in update 原因 web项目下缺少 WEB INF web xml 在servl
  • 【AWS】API Gateway创建Rest API--从S3下载文件

    一 背景 在不给AK SK的前提下 用户查看s3上文件 从s3下载文件 二 创建API 1 打开API Gateway 点击创建API 选择REST API REST API和HTTP API区别 来自AWS官网 REST API 和 HT
  • 算法——查找

    文章目录 一 基本概念和评价 1 相关概念 2 查找表 2 1 常见操作 2 2 分类 3 查找算法的评价指标 二 线性结构查找 1 顺序查找算法 1 1 定义 1 2 算法思想 1 3 特点 1 4 分类 1 无哨兵的无序线性表的顺序查找
  • Unity 安卓报错 failed to extract resources needed by IL2cpp

    Unity打出来的包在自己的PC放置好文件后 运行能够正常运行 但是git提交之后 别的机器拉代码下来报错 failed to extract resources needed by IL2cpp 这里推测原因是 安卓包打出来的Asset
  • TikTok逆向,全球的小姐姐们,我来啦!

    作者 AYJk 链接 https juejin im post 5c19a38ae51d453e0a209256 开源地址 首先抛出GitHub地址吧 多多支持指点 谢谢 AYTikTokPod https github com AYJk
  • 知识索引目录

    author skate time 2012 11 22 存储 io系统的压力测试工具 fio http blog csdn net wyzxg article details 7454072 iozone使用 http blog csdn
  • 从零开发一套完整的react项目开发环境

    不管是工作需要还是面试加分 除了Vue相关技术以外 React技术栈也已经成为了前端开发工程师必备的技术点 接下来 我将从零开发一套完整的React全家桶项目开发环境 提供给需要的同行小伙伴观看也方便自己以后复习 篇幅很长 请需要的小伙伴耐
  • ZLMediaKit+wvp-GB28181-pro 安装文档

    文章目录 前言 1 安装zlm 1 1 镜像说明 1 2 docker安装 1 2 1 docker安装命令 1 2 2 docker compose安装 1 3 zlm配置和日志重点说明 2 安装wvp 2 1 目录结构说明 2 1 1
  • 汇编宏伪指令介绍

    1 汇编宏伪指令介绍 macro macname macargs endm 1 macro 和 endm 表示宏定义的开始和结束 2 macro 后面接着宏定义的名字 然后是参数 参数后面的宏定义的实现 3 在宏定义中使用参数 需要添加前缀
  • Eclipse中Web项目开发与Tomcat发布的的路径问题详解

    本人以前对Web项目的开发路径和发布路径等一直都很懵逼 今天找到了一片文章 里面写得很详细 在这里转载分享给大家 https www cnblogs com teach p 5669873 html
  • STM32F407输入捕获应用--PWM 输入模式测量脉冲频率与宽度

    STM32F407输入捕获应用 PWM 输入模式测量脉冲频率与宽度 一 测量脉宽或者频率 二 PWM 输入模式 三 软件实现 3 1 硬件准备 3 2代码 3 4 验证 输入捕获一般应用在两个方面 一个方面是脉冲跳变沿时间测量 另一方面 是
  • PyTorch-06 过拟合&欠拟合、Train-Val-Test划分、Regularization减轻防止overfitting、动量与学习率衰减、其他技巧Early Stop,Dropout

    PyTorch 06 过拟合 欠拟合 Train Val Test划分 Regularization减轻防止overfitting 动量与学习率衰减 其他技巧Tricks Early Stop Dropout 一 过拟合 欠拟合 讨论过拟合
  • java实现@Valid自定义注解

    Valid注解是什么 用于验证被注解对象是否符合要求 当不符合要求时就会在方法中返回message的错误提示信息 自定义注解 Target ElementType FIELD Documented Retention RetentionPo
  • Linux 内核加速支持 Rust 开发;中科院计划每半年升级一次 RISC-V 芯片;Python 3.10.1 发布

    整理 宋彤彤 责编 屠敏 开源吞噬世界的趋势下 借助开源软件 基于开源协议 任何人都可以得到项目的源代码 加以学习 修改 甚至是重新分发 关注 开源日报 一文速览国内外今日的开源大事件吧 一分钟速览新闻点 2022 年 Linux 内核或将
  • C#使用Socket实现一个socket服务器与多个socket客户端通信

    在分布式调度系统中 如果要实现调度服务器与多台计算节点服务器之间通信 采用socket来实现是一种实现方式 当然我们也可以通过数据存储任务 子节点来完成任务 但是往往使用数据作为任务存储都需要定制开发 要维护数据库中任务记录状态等等 开发的