C#服务端与多客户端进行Tcp通信

1.服务端(Tcp Server)

①创建监听套接字

 //负责监听客户端请求连接信号的套接字  
Socket listenSocket = null;
//(IPv4协议,数据流双向,TCP协议)
listenSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.tcp);

②创建一个网络端点

 //网络端点m_Endpoint 需要IP地址和端口号
 //端口号为0 以指定任何可用端口。
 IPEndPoint m_Endpoint = new IPEndPoint(IPAddress.Parse(txb_ip.Text.Trim()), int.Parse(txb_port.Text.Trim())); 

③将监听套接字和网络端点绑定
绑定该网络端点后,只要有客户端向该网络端点发送连接请求,就会被监听套接字识别到。

 //绑定网络端点
listenSocket.Bind(m_Endpoint);
//将监听Socket置于侦听状态,(backlog):挂起连接队列的最大长度。
listenSocket.Listen(10);

④启动监听套接字的侦听模式

//backlog:监听连接队列的最大长度。
listenSocket.Listen(10);

⑤创建负责通信的套接字

Socket interactSocket = null;
//阻塞,直到接收到客户端连接请求,生成与客户端通信的套接字保存
interactSocket = listenSocket.Accept();

⑥使用通信套接字给对应的客户端发送信息

interactSocket.Send("hello world!");  

⑦使用通信套接字接收客户端发送过来的信息

//创建一个内存缓冲区 其大小为1024*1024字节  即1M
byte[] arrServerRecMsg = new byte[1024 * 1024];
//将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
int length = interactSocket.Receive(arrServerRecMsg);

⑧关闭监听套接字和通信套接字

listenSocket.Close();
interactSocket.Close();

2.服务端Demo(Tcp Server)

在这里插入图片描述
功能:
①可单发或者群发信息
②可单个屏蔽选中客户端或者全部屏蔽客户端
③可单个解除屏蔽,也可以全部屏蔽解除
④关闭服务器,切断所有用户连接

3.客户端(Tcp Client)

①创建一个客户端套接字

//IP4寻址协议,流式双向,TCP协议
Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

②请求连接服务器所在的网络端点

//创建一个网络端点,内容为服务器ip和端口号
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(this.txtIP.Text.Trim()), int.Parse(this.txtPort.Text.Trim()));
//请求连接,连接失败报异常
socketClient.Connect(endpoint);

③向服务器发送信息

//将输入的内容字符串转换为机器可以识别的字节数组
byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
//调用客户端套接字发送字节数组
socketClient.Send(arrClientSendMsg);

④接收来自服务器的信息

//定义一个1M的内存缓冲区 用于临时性存储接收到的信息
byte[] arrRecMsg = new byte[1024 * 1024];
//将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度
int length = socketClient.Receive(arrRecMsg);

⑤关闭客户端套接字

socketClient.Close();

4.客户端Demo(Tcp Client)

在这里插入图片描述
功能:
①负责与服务器信息通信
②服务器关闭,可自动被切断连接

5.服务端TcpListener(Tcp Server)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FrmTcpServerV2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }
        TcpListener tcpServer;//负责监听客户端的连接请求
        Thread listenThread;//监听线程
        Dictionary<string, Socket> dicClientSockets = new Dictionary<string, Socket>();//客户端套接字集合
        Dictionary<string, Thread> dicRecvMsgThreads = new Dictionary<string, Thread>();//接收信息的线程集合

        //开启服务器
        private void btn_start_Click(object sender, EventArgs e)
        {
            if (btn_start.Text == "开启服务端")
            {
                tcpServer = new TcpListener(IPAddress.Parse(txb_ip.Text.Trim()), int.Parse(txb_port.Text.Trim()));
                tcpServer.Start();//开启连接请求


                ThreadStart threadFun = new ThreadStart(ListenConnRequst);//创建一个监听线程执行的委托
                listenThread = new Thread(threadFun);//创建一个监听线程
                listenThread.IsBackground = true;//后台运行线程
                listenThread.Start();//启动线程
                btn_start.Text = "关闭服务端";
                AddLog("服务器开启!");
            }
            else
            {
                tcpServer.Stop();//关闭监听
                //断开所有客户端的连接
                for (int i = 0; i < listb_client.Items.Count; i++)
                {
                    dicClientSockets[listb_client.Items[i].ToString()].Close();
                }
                btn_start.Text = "开启服务端";
                AddLog("服务器关闭!");
            }
        }

        //监听客户端的连接请求
        public void ListenConnRequst()
        {
            while (true)
            {
                try
                {
                    Socket clientSocket = tcpServer.AcceptSocket();
                    ParameterizedThreadStart ThreadFun = new ParameterizedThreadStart(RecvMsg);//创建一个obj传参的线程委托
                    Thread recvMsgThread = new Thread(ThreadFun);//创建一个线程
                    recvMsgThread.IsBackground = true;//设置线程为后台线程
                    recvMsgThread.Start(clientSocket);//启动线程并且传入参数clientSocket套接字
                    dicClientSockets.Add(clientSocket.RemoteEndPoint.ToString(), clientSocket);//将套接字加入集合
                    dicRecvMsgThreads.Add(clientSocket.RemoteEndPoint.ToString(), recvMsgThread);//将信息接收线程加入集合
                    listb_client.Items.Add(clientSocket.RemoteEndPoint.ToString());
                }
                catch (Exception)
                {
                }
            }
        }
        public void RecvMsg(Object obj)
        {
            Socket clientSocket = (Socket)obj;//将传入的参数类型转换一下
            string str = clientSocket.RemoteEndPoint.ToString();
            while (true)
            {
                try
                {
                    //创建1M的缓存空间
                    byte[] buffer = new byte[1024 * 1024];
                    int length = clientSocket.Receive(buffer);//返回实际接收到的长度
                    string msgStr = Encoding.UTF8.GetString(buffer, 0, length);//转换成UTF-8的格式
                    if (length != 0)
                    {
                        AddLog(DateTime.Now.ToLongTimeString() +" 客户端"+str+" : "+msgStr);
                    }
                }
                catch (Exception)
                {
                    //清空集合对应的套接字
                    listb_client.Items.Remove(str);
                    dicClientSockets.Remove(str);
                    dicRecvMsgThreads.Remove(str);
                    break;
                }
            }
        }

        //添加日志
        public void AddLog(string str)
        {
            try
            {
                if (listb_log.Items.Count > 100)
                {
                    listb_log.Items.RemoveAt(99);
                }
                listb_log.Items.Insert(0, str);
            }
            catch (Exception f)
            {
                MessageBox.Show(f.ToString());
            }
        }

        //单发信息
        private void btn_singlesend_Click(object sender, EventArgs e)
        {
            int index = listb_client.SelectedIndex;
            if (index == -1)
            {
                MessageBox.Show("请选择客户端!");
                return;
            }
            string msgStr = txb_msg.Text.Trim();
            if (!string.IsNullOrEmpty(msgStr))
            {
                byte[] arrMsg = Encoding.UTF8.GetBytes(msgStr);
                dicClientSockets[listb_client.SelectedItem.ToString()].Send(arrMsg);
            }
        }

        //群发信息
        private void btn_allsend_Click(object sender, EventArgs e)
        {
            string msgStr = txb_msg.Text.Trim();
            if (!string.IsNullOrEmpty(msgStr))
            {
                byte[] arrMsg = Encoding.UTF8.GetBytes(msgStr);
                for (int i = 0; i < listb_client.Items.Count; i++)
                {
                    dicClientSockets[listb_client.Items[i].ToString()].Send(arrMsg);
                }
                
            }
        }
    }
}

6.客户端TcpClient(Tcp Client)

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

        TcpClient newClient;//客户端
        Socket ClientSocket;//通信套接字

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (button1.Text == "连接")
                {
                    newClient = new TcpClient(textBox1.Text, int.Parse(textBox2.Text));
                    ClientSocket = newClient.Client;
                    ClientSocket.ReceiveTimeout = 1000;
                    button1.Text = "断开";
                    AddLog("服务端连接成功!");

                    string sendMsg = "客户端连接服务端成功!";
                    //将输入的内容字符串转换为机器可以识别的字节数组
                    byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                    //调用客户端套接字发送字节数组
                    ClientSocket.Send(arrClientSendMsg);

                    //定义一个1M的内存缓冲区 用于临时性存储接收到的信息
                    byte[] arrRecMsg = new byte[1024 * 1024];

                    //将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度
                    int length = ClientSocket.Receive(arrRecMsg);

                    //将套接字获取到的字节数组转换为人可以看懂的字符串
                    string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                    AddLog(strRecMsg);
                }
                else
                {               
                    newClient.Close();
                    button1.Text = "连接";
                    AddLog("服务端断开成功!");
                }
            }
            catch (Exception)
            {
                MessageBox.Show("连接失败!");
            }
        }
        public void AddLog(string str)
        {
            if (listBox1.Items.Count>100)
            {
                listBox1.Items.RemoveAt(99);
            }
            listBox1.Items.Insert(0,str);
        }
    }
}

7.代码链接及效果展示视屏链接

开源代码链接(含客户端和服务端):
①V1
https://download.csdn.net/download/adsd1233123/21718750?spm=1001.2014.3001.5503

②V2
https://download.csdn.net/download/adsd1233123/21751534?spm=1001.2014.3001.5503

效果展示视屏如下:
https://www.bilibili.com/video/BV1Gq4y1T7nJ?spm_id_from=0.0.dynamic.content.click

  • 10
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱搞事的程小猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值