①创建监听套接字
//负责监听客户端请求连接信号的套接字
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();
功能:
①可单发或者群发信息
②可单个屏蔽选中客户端或者全部屏蔽客户端
③可单个解除屏蔽,也可以全部屏蔽解除
④关闭服务器,切断所有用户连接
①创建一个客户端套接字
//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();
功能:
①负责与服务器信息通信
②服务器关闭,可自动被切断连接
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);
}
}
}
}
}
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);
}
}
}
开源代码链接(含客户端和服务端):
①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