C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

作者:风之_诉 时间:2022-03-08 23:48:07 

扩展:
由于server端是存储了所有server与client的连接对象,因此我们是可以基于此demo的基础上实现聊天系统:

* 每当一个与用户发言时,是由server接收到的某个用户的发言信息的,此时服务器端可以通过循环发送该用户发送的信息给每个已经连接连接的用户(排除发送者)。

Server端代码:


class Program
{
 //创建一个和客户端通信的套接字
 static Socket SocketWatch = null;
 //定义一个集合,存储客户端信息
 static Dictionary<string, Socket> ClientConnectionItems = new Dictionary<string, Socket> { };

static void Main(string[] args)
 {
   //端口号(用来监听的)
   int port = 6000;

//string host = "127.0.0.1";
   //IPAddress ip = IPAddress.Parse(host);
   IPAddress ip = IPAddress.Any;

//将IP地址和端口号绑定到网络节点point上
   IPEndPoint ipe = new IPEndPoint(ip, port);

//定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
   SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   //监听绑定的网络节点
   SocketWatch.Bind(ipe);
   //将套接字的监听队列长度限制为20
   SocketWatch.Listen(20);

//负责监听客户端的线程:创建一个监听线程
   Thread threadwatch = new Thread(WatchConnecting);
   //将窗体线程设置为与后台同步,随着主线程结束而结束
   threadwatch.IsBackground = true;
   //启动线程  
   threadwatch.Start();

Console.WriteLine("开启监听......");
   Console.WriteLine("点击输入任意数据回车退出程序......");
   Console.ReadKey();

SocketWatch.Close();

//Socket serverSocket = null;

//int i=1;
   //while (true)
   //{
   //  //receive message
   //  serverSocket = SocketWatch.Accept();
   //  Console.WriteLine("连接已经建立!");
   //  string recStr = "";
   //  byte[] recByte = new byte[4096];
   //  int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
   //  //recStr += Encoding.ASCII.GetString(recByte, 0, bytes);
   //  recStr += Encoding.GetEncoding("utf-8").GetString(recByte, 0, bytes);

//  //send message
   //  Console.WriteLine(recStr);

//  Console.Write("请输入内容:");
   //  string sendStr = Console.ReadLine();

//  //byte[] sendByte = Encoding.ASCII.GetBytes(sendStr);
   //  byte[] sendByte = Encoding.GetEncoding("utf-8").GetBytes(sendStr);

//  //Thread.Sleep(4000);

//  serverSocket.Send(sendByte, sendByte.Length, 0);
   //  serverSocket.Close();
   //  if (i >= 100)
   //  {
   //    break;
   //  }
   //  i++;
   //}

//sSocket.Close();
   //Console.WriteLine("连接关闭!");

//Console.ReadLine();
 }

//监听客户端发来的请求
 static void WatchConnecting()
 {
   Socket connection = null;

//持续不断监听客户端发来的请求  
   while (true)
   {
     try
     {
       connection = SocketWatch.Accept();
     }
     catch (Exception ex)
     {
       //提示套接字监听异常  
       Console.WriteLine(ex.Message);
       break;
     }

//客户端网络结点号
     string remoteEndPoint = connection.RemoteEndPoint.ToString();
     //添加客户端信息
     ClientConnectionItems.Add(remoteEndPoint, connection);
     //显示与客户端连接情况
     Console.WriteLine("\r\n[客户端\"" + remoteEndPoint + "\"建立连接成功! 客户端数量:" + ClientConnectionItems .Count+ "]");

//获取客户端的IP和端口号
     IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
     int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port;

//让客户显示"连接成功的"的信息
     string sendmsg = "[" + "本地IP:" + clientIP + " 本地端口:" + clientPort.ToString() + " 连接服务端成功!]";
     byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
     connection.Send(arrSendMsg);

//创建一个通信线程  
     Thread thread = new Thread(recv);
     //设置为后台线程,随着主线程退出而退出
     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("\r\n[客户端:" + socketServer.RemoteEndPoint + " 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")+ "]\r\n" + strSRecMsg);

//Thread.Sleep(3000);
       //socketServer.Send(Encoding.UTF8.GetBytes("[" + socketServer.RemoteEndPoint + "]:"+strSRecMsg));
       //发送客户端数据
       if (ClientConnectionItems.Count > 0)
       {
         foreach (var socketTemp in ClientConnectionItems)
         {
           socketTemp.Value.Send(Encoding.UTF8.GetBytes("[" + socketServer.RemoteEndPoint + "]:" + strSRecMsg));
         }
       }
     }
     catch (Exception)
     {
       ClientConnectionItems.Remove(socketServer.RemoteEndPoint.ToString());
       //提示套接字监听异常
       Console.WriteLine("\r\n[客户端\"" + socketServer.RemoteEndPoint + "\"已经中断连接! 客户端数量:" + ClientConnectionItems.Count+"]");
       //关闭之前accept出来的和客户端进行通信的套接字
       socketServer.Close();
       break;
     }
   }
 }
}

Client端代码:


class Program
{
 //创建1个客户端套接字和1个负责监听服务端请求的线程
 static Thread ThreadClient = null;
 static Socket SocketClient = null;

static void Main(string[] args)
 {
   try
   {
     int port = 6000;
     string host = "127.0.0.1";//服务器端ip地址

IPAddress ip = IPAddress.Parse(host);
     IPEndPoint ipe = new IPEndPoint(ip, port);

//定义一个套接字监听
     SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

try
     {
       //客户端套接字连接到网络节点上,用的是Connect
       SocketClient.Connect(ipe);
     }
     catch (Exception)
     {
       Console.WriteLine("连接失败!\r\n");
       Console.ReadLine();
       return;
     }

ThreadClient = new Thread(Recv);
     ThreadClient.IsBackground = true;
     ThreadClient.Start();

Thread.Sleep(1000);
     Console.WriteLine("请输入内容<按Enter键发送>:\r\n");
     while(true)
     {
       string sendStr = Console.ReadLine();
       ClientSendMsg(sendStr);
     }

//int i = 1;
     //while (true)
     //{
     //  Console.Write("请输入内容:");
     //  string sendStr = Console.ReadLine();

//  Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     //  clientSocket.Connect(ipe);
     //  //send message
     //  //byte[] sendBytes = Encoding.ASCII.GetBytes(sendStr);
     //  byte[] sendBytes = Encoding.GetEncoding("utf-8").GetBytes(sendStr);

//  //Thread.Sleep(4000);

//  clientSocket.Send(sendBytes);

//  //receive message
     //  string recStr = "";
     //  byte[] recBytes = new byte[4096];
     //  int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
     //  //recStr += Encoding.ASCII.GetString(recBytes, 0, bytes);
     //  recStr += Encoding.GetEncoding("utf-8").GetString(recBytes, 0, bytes);
     //  Console.WriteLine(recStr);

//  clientSocket.Close();
     //  if (i >= 100)
     //  {
     //    break;
     //  }
     //  i++;
     //}

//Console.ReadLine();
     //return;

//string result = String.Empty;

}
   catch (Exception ex)
   {
     Console.WriteLine(ex.Message);
     Console.ReadLine();
   }
 }

//接收服务端发来信息的方法  
 public static 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)
       {
         Console.WriteLine("\r\n服务器:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "\r\n" + strRevMsg+"\r\n");

}
       else
       {
         Console.WriteLine(strRevMsg + "\r\n");
         x = 1;
       }
     }
     catch (Exception ex)
     {
       Console.WriteLine("远程服务器已经中断连接!" + ex.Message + "\r\n");
       break;
     }
   }
 }

//发送字符信息到服务端的方法
 public static void ClientSendMsg(string sendMsg)
 {
   //将输入的内容字符串转换为机器可以识别的字节数组  
   byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
   //调用客户端套接字发送字节数组  
   SocketClient.Send(arrClientSendMsg);
 }  
}

测试结果:

server端:

C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

client端:

C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

代码下载地址:C-Socket_jb51.zip

来源:https://blog.csdn.net/luming666/article/details/79125453

标签:C#,Socket,服务器,客户端,通信
0
投稿

猜你喜欢

  • 使用C#开发OPC Server服务器源码解析

    2021-05-30 04:30:14
  • Android 显示GIF图片实例详解

    2023-08-06 09:11:52
  • Java后端学习精华之TCP通信传输协议详解

    2021-08-06 03:15:42
  • java实现mp3合并的方法

    2023-11-09 03:47:08
  • 详解C语言实现猜数字游戏

    2023-11-03 04:58:51
  • springboot通过注解、接口创建定时任务详解

    2021-06-05 06:00:29
  • C#使用itextsharp生成PDF文件的实现代码

    2022-05-18 03:21:27
  • SpringBoot事件发布和监听详解

    2022-04-18 02:39:59
  • 深入理解Java序列化与反序列化

    2023-01-24 00:27:53
  • Spark JDBC操作MySQL方式详细讲解

    2021-05-24 12:41:51
  • Redis原子计数器incr,防止并发请求操作

    2021-07-03 13:35:15
  • Java创建多线程的两种方式对比

    2023-09-14 21:02:49
  • Java中Cookie和Session详解及区别总结

    2022-08-24 21:55:10
  • unity学习教程之定制脚本模板示例代码

    2022-02-18 05:07:08
  • Java Timezone类常见问题_动力节点Java学院整理

    2023-08-23 01:30:11
  •  Java图形化界面编程实现简单计算器

    2021-06-06 17:23:09
  • Android编程中context及全局变量实例详解

    2023-11-17 05:58:40
  • Java 替换word文档文字并指定位置插入图片

    2023-08-12 22:02:25
  • 浅谈Java操作符与其优先级

    2022-09-27 19:42:44
  • springboot+nginx+https+linux实现负载均衡加域名访问简单测试

    2022-04-26 22:35:13
  • asp之家 软件编程 m.aspxhome.com