C# Socket通信
转自:https://www.cnblogs.com/zeussbook/p/18325935
一、通信协议 TCP/UDP
TCP
传输控制协议Transmission Control Protocol是一种面向连接的、可靠的、基于字节流的运输层通信协议,在简化的计算机网络OSI模型中,它完成传输层所指定的功能。优点传输安全,缺点效率相对低。
UDP
用户数据报协议 User Datagram ProtocolUDP是一个简单的面向无连接的,不可靠的数据报的传输层(transport layer)协议。优点传输速度快,缺点不安全。
二、SOCKET
socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。Socket是面向客户/服务器模型而设计的。通信的一方扮演客户机的角色,另一方扮演服务器的角色。服务器在运行中一直监听套接字指定的传输层端口,并等待着客户机的连接请求。当服务器端收到客户机发来的连接请求以后,服务器会接受客户机的连接请求,双方建立连接后,就可进行数据的传递。服务器端可以一对多。
支持TCP/UDP传输协议
IP找设备,port端口找到服务器上要通讯的程序。
建立socket对象,负责收发数据
三、SOCKET代码实现
客户端
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp7
{
public partial class Form1 : Form
{
private Socket socket;
Encoding encoding = Encoding.Unicode;
public Form1()
{
InitializeComponent();
load();
}
/// <summary>
/// 加载
/// </summary>
private void load()
{
//1.获取本地网络分配给你的IP
IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
//第二步:
foreach (var item in hostEntry.AddressList)
{
//3.判断是否是协议版本V4
if (item.AddressFamily == AddressFamily.InterNetwork)
{
cB_IPs.Items.Add(item);
}
}
//添加本机IP
cB_IPs.Items.Add("127.0.0.1");
cB_IPs.Items.Add("192.168.110.96");
cB_IPs.SelectedIndex = 0;//默认选中0个对象
}
/// <summary>
/// 连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button2_Click(object sender, EventArgs e)
{
//第一步:初始化套接字对象
socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
//第二步:连接
socket.Connect(cB_IPs.Text,(int)numericUpDown1.Value);
MessageBox.Show("连接成功!");
Task.Run(() =>
{
while (true)
{
//监测服务器是否下线
try
{
bool yes = socket.Poll(1, SelectMode.SelectRead);
if (yes)
{
MessageBox.Show("服务器已下线!");
continue;
}
Reception();
}
catch (Exception ex)
{
MessageBox.Show("服务器连接异常!"+ex.Message);
return;
}
}
});
}
catch(Exception ex)
{
//连接失败
MessageBox.Show($"连接失败:{ex}");
}
}
/// <summary>
/// 断开
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button1_Click(object sender, EventArgs e)
{
if (socket != null && socket.Connected)
{
socket.Close();
MessageBox.Show("断开连接");
}
}
/// <summary>
/// 发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button3_Click(object sender, EventArgs e)
{
//1.判断连接状态
if (socket != null && socket.Connected)
{
//2.字符串转换二进制
byte[] data = encoding.GetBytes(richTextBox2.Text);
try
{
//3.发送
socket.Send(data);
}
catch (Exception ex)
{
MessageBox.Show($"发送失败:{ex}");
}
}
}
/// <summary>
/// 接收数据
/// </summary>
public void Reception()
{
byte[] data = new byte[1024 * 2];
try
{
//接收
int length = socket.Receive(data);
//判断是否有发送字节
if (length > 0)
{
richTextBox1.Invoke(new Action(() => {
richTextBox1.AppendText($" [{DateTime.Now.ToString("HH:mm:ss")}]:{encoding.GetString(data, 0, length)}" + Environment.NewLine);
}));
}
}
catch (Exception ex)
{
MessageBox.Show($"接收失败:{ex}");
}
}
/// <summary>
/// 打开服务器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button4_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.Show();
}
}
}
服务端
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp7
{
public partial class Form2 : Form
{
//服务器套接字
private Socket socket;
//客户端连接
List<Socket> sockets = new List<Socket>();
//服务器连接标识
bool connectingFlag;
Encoding encoding = Encoding.Unicode;
public Form2()
{
InitializeComponent();
load();
}
private void Label3_Click(object sender, EventArgs e)
{
}
/// <summary>
/// 加载
/// </summary>
private void load()
{
//1.获取本地网络分配给你的IP
System.Net.IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
//第二步:
foreach (var item in hostEntry.AddressList)
{
//3.判断是否是协议版本V4
if (item.AddressFamily == AddressFamily.InterNetwork)
{
cB_IPs.Items.Add(item);
}
}
//添加本机IP
cB_IPs.Items.Add("127.0.0.1");
cB_IPs.Items.Add("192.168.110.96");
cB_IPs.SelectedIndex = 0;//默认选中0个对象
}
/// <summary>
/// 打开服务器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button2_Click(object sender, EventArgs e)
{
//1.初始化
socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//2.监听
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(cB_IPs.Text) ,(int)numericUpDown1.Value);
try
{
socket.Bind(iPEndPoint);//监听
socket.Listen(10);//一秒可以监听多少个客户端连接
MessageBox.Show("服务器打开成功");
connectingFlag = true;
#region 监视客户端
//监听客户端
ThreadPool.QueueUserWorkItem((Object o) =>
{
while (true)
{
//判断服务器是否连接
if (!connectingFlag)
{
break;
}
Socket socket1 = socket.Accept();//客户端连接
sockets.Add(socket1);
//获取客户端连接IP和端口
IPEndPoint iPEndPoint1 = (IPEndPoint)socket1.RemoteEndPoint;
//显示到数据表格
dataGridView1.Invoke(new Action(() =>
{
dataGridView1.Rows.Add(iPEndPoint1.Address, iPEndPoint1.Port);
}));
}
});
#endregion
#region 监视客户端发送数据
Task.Run(() =>
{
while (true)
{
//判断服务器是否连接
if (!connectingFlag)
{
break;
}
//1.判断是否有客户端
if (sockets.Count == 0)
{
continue;
}
//2.循环监视客户端
for (int i = sockets.Count-1; i >=0; i--)
{
//3.判断用户是否下线
bool downStatus = sockets[i].Poll(1,SelectMode.SelectRead);
//true下线
if (downStatus)
{
dataGridView1.Invoke(new Action(() =>
{
dataGridView1.Rows.RemoveAt(i);//删除显示
}));
sockets.RemoveAt(i);//删除客户端
continue;
}
try
{
//4.接收用户信息
byte[] data = new byte[1024];
int dataLength = sockets[i].Receive(data);
//判断用户是否发送数据
if (dataLength > 0)
{
//解析用户发送数据
string send = encoding.GetString(data);
//获取发送用户ip和端口
IPEndPoint iPEndPoint1 = (IPEndPoint)sockets[i].RemoteEndPoint;
//显示发送信息
richTextBox2.Invoke(new Action(() =>
{
richTextBox2.AppendText($"{iPEndPoint1.Address} [{DateTime.Now.ToString("HH:mm:ss")}]:{encoding.GetString(data, 0, dataLength)}" + Environment.NewLine);
}));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
});
#endregion
}
catch (Exception ex)
{
MessageBox.Show($"服务端开始失败:{ex}");
}
}
/// <summary>
/// 发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button3_Click(object sender, EventArgs e)
{
try
{
//判断是否群发
int index = dataGridView1.CurrentCell.RowIndex;
//判断是否群发
if (checkBox1.Checked)
{
foreach (Socket item in sockets)
{
item.Send(encoding.GetBytes(richTextBox1.Text));
}
}
else
{
//获取客户端socket
Socket socket = sockets[index];
//发送
socket.Send(encoding.GetBytes(richTextBox1.Text));
}
}
catch (Exception ex)
{
MessageBox.Show($"发送失败:{ex}");
}
}
/// <summary>
/// 断开服务器连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button1_Click(object sender, EventArgs e)
{
if (connectingFlag)
{
connectingFlag = false;
sockets.Clear();//清除集合
dataGridView1.Rows.Clear();//清除显示
socket.Close();//关闭服务器
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· Qt个人项目总结 —— MySQL数据库查询与断言