基于C#的Socket通信
同步非阻塞 UDP
//声明全局引用
Socket UdpSocket;
Thread recvThread;
bool recvThreadStop;
//自动添加本地ip
string localhost = Dns.GetHostName();
IPAddress[] local_ip = Dns.GetHostAddresses(localhost);
foreach (IPAddress ip in local_ip)
{
comboBox_IP.Items.Add(ip);
}
//实例化一个Socket对象,并绑定到指定端口
IPEndPoint Point;
Point = new IPEndPoint(IPAddress.Parse(comboBox_IP.Text), Convert.ToInt16(textBox_Port.Text));
UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
UdpSocket.Bind(Point);
//实例化一个线程,用于接收远程数据
recvThread = new Thread(new ThreadStart(RecvData));
recvThreadStop = false;
recvThread.Start();
//线程的具体内容
private void RecvData()
{
UdpSocket.Blocking = false;
byte[] buffer = new byte[65536];
EndPoint Point = new IPEndPoint(IPAddress.Any, 0);
while (!recvThreadStop)
{
if (UdpSocket.Available == 0) continue;
int count = UdpSocket.ReceiveFrom(buffer, ref Point);
UdpSocket.SendTo(buffer, count, 0, Point);
}
UdpSocket.Close();
}
//向远程端口发送数据
IPEndPoint Point;
Point = new IPEndPoint(IPAddress.Parse(textBox_Remote.Text), Convert.ToInt16(textBox.Text));
byte[] sendData = Encoding.UTF8.GetBytes(textBox.Text);
UdpSocket.SendTo(sendData, Point);
//终止UDP传输
recvThreadStop = true;
同步非阻塞 TCP Client
//声明全局引用
Socket TcpSocket;
Thread recvThread;
bool recvThreadStop;
//自动添加本地ip
string localhost = Dns.GetHostName();
IPAddress[] local_ip = Dns.GetHostAddresses(localhost);
foreach (IPAddress ip in local_ip)
{
comboBox_IP.Items.Add(ip);
}
//实例化一个Socket对象,并连接到服务端
IPEndPoint Point;
Point = new IPEndPoint(IPAddress.Parse(comboBox_IP.Text), Convert.ToInt16(textBox_Port.Text));
TcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
TcpSocket.Connect(Point);
//实例化一个线程,用于接收远程数据
recvThread = new Thread(new ThreadStart(RecvData));
recvThreadStop = false;
recvThread.Start();
//线程的具体内容
private void RecvData()
{
byte[] buffer = new byte[65536];
while (!recvThreadStop)
{
if (!TcpSocket.Poll(10, SelectMode.SelectRead)) continue;
int count = TcpSocket.Receive(buffer);
if (count > 0)
TcpSocket.Send(buffer, count, SocketFlags.None);
else break;
}
TcpSocket.Close();
}
//向远程端口发送数据
byte[] sendData = Encoding.UTF8.GetBytes(textBox.Text);
TcpSocket.Send(sendData);
//TCP断开连接
recvThreadStop = true;
同步非阻塞 TCP Server
//定义委托类型(回调函数类型)
delegate int AddItemCallBack(object item);
delegate void RemoveItemCallBack(object item);
//声明全局引用
Socket listenSocket;
Thread listenThread;
bool listenThreadStop;
AddItemCallBack addItemCallBack;
RemoveItemCallBack removeItemCallBack;
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
//自动添加本地ip
string localhost = Dns.GetHostName();
IPAddress[] local_ip = Dns.GetHostAddresses(localhost);
foreach (IPAddress ip in local_ip)
{
comboBox.Items.Add(ip);
}
//实例化回调函数
addItemCallBack = comboBox.Items.Add;
removeItemCallBack = comboBox.Items.Remove;
//实例化一个Socket对象,并开始监听
IPEndPoint Point;
Point = new IPEndPoint(IPAddress.Parse(comboBox_IP.Text), Convert.ToInt16(textBox_Port.Text));
listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(Point);
listenSocket.Listen(10);
//实例化一个线程,用于监听客户端
listenThread = new Thread(new ThreadStart(Listening));
listenThreadStop = false;
listenThread.Start();
//父线程的具体内容
private void Listening()
{
listenSocket.Blocking = false;
while (!listenThreadStop)
{
try
{
Socket TcpSocket = listenSocket.Accept();
string strPoint = TcpSocket.RemoteEndPoint.ToString();
comboBox.Invoke(addItemCallBack, strPoint);
dicSocket.Add(strPoint, TcpSocket);
Thread recvThread = new Thread(new ParameterizedThreadStart(RecvData));
recvThread.Start(TcpSocket);
}
catch { }
}
listenSocket.Close();
}
//子线程的具体内容
private void RecvData(object obj)
{
Socket TcpSocket = obj as Socket;
byte[] buffer = new byte[65536];
while (!listenThreadStop)
{
if (!TcpSocket.Poll(10, SelectMode.SelectRead)) continue;
int count = TcpSocket.Receive(buffer);
if (count > 0)
TcpSocket.Send(buffer, count, SocketFlags.None);
else break;
}
comboBox.Invoke(removeItemCallBack, TcpSocket.RemoteEndPoint.ToString());
dicSocket.Remove(TcpSocket.RemoteEndPoint.ToString());
TcpSocket.Close();
}
//用字典实现向指定端口发送数据
string point = comboBox.SelectedItem.ToString();
byte[] sendData = Encoding.UTF8.GetBytes(textBox.Text);
dicSocket[point].Send(sendData);
//TCP断开连接
listenThreadStop = true;
异步(非阻塞) TCP Client
异步通常是非阻塞的
//用于在异步接收中传递信息的类
public class StateObject
{
public const int BufferSize = 65536;
public byte[] buffer = new byte[BufferSize];
public Socket workSocket = null;
public bool recvDone = true;
public bool disconnect = false;
}
//声明全局引用
Socket TcpSocket;
bool recvStop;
static ManualResetEvent connectDone;
//自动添加本地ip
string localhost = Dns.GetHostName();
IPAddress[] local_ip = Dns.GetHostAddresses(localhost);
foreach (IPAddress ip in local_ip)
{
comboBox_IP.Items.Add(ip);
}
//实例化一个Socket对象
IPEndPoint Point;
Point = new IPEndPoint(IPAddress.Parse(comboBox_IP.Text), Convert.ToInt16(textBox_Port.Text));
TcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//开始异步连接
recvStop = false;
connectDone = new ManualResetEvent(false);
TcpSocket.BeginConnect(Point, new AsyncCallback(ConnectCallback), TcpSocket);
connectDone.WaitOne();
//异步连接回调函数
private void ConnectCallback(IAsyncResult ar)
{
Socket TcpSocket = (Socket)ar.AsyncState;
TcpSocket.EndConnect(ar);
connectDone.Set();
StateObject state = new StateObject();
state.workSocket = TcpSocket;
while (!recvStop)
{
if (!state.recvDone) continue;
if (state.disconnect) break;
state.recvDone = false;
TcpSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(RecvCallback), state);
}
TcpSocket.Close();
}
//异步接收回调函数
private void RecvCallback(IAsyncResult ar)
{
if (recvStop) return;
StateObject state = (StateObject)ar.AsyncState;
Socket TcpSocket = state.workSocket;
int count = TcpSocket.EndReceive(ar);
if (count > 0)
TcpSocket.BeginSend(state.buffer, 0, count, 0, null, null);
else
state.disconnect = true;
state.recvDone = true;
}
//向远程端口发送数据
byte[] sendData = Encoding.UTF8.GetBytes(textBox.Text);
TcpSocket.BeginSend(sendData, 0, sendData.Length, 0, null, null);
//TCP断开连接
recvThreadStop = true;
异步(非阻塞) TCP Server
异步通常是非阻塞的
//用于在异步接收中传递信息的类
public class StateObject
{
public const int BufferSize = 65536;
public byte[] buffer = new byte[BufferSize];
public Socket workSocket = null;
public bool recvDone = true;
public bool disconnect = false;
}
//定义委托类型(回调函数类型)
delegate int AddItemCallBack(object item);
delegate void RemoveItemCallBack(object item);
//声明全局引用
Socket listenSocket;
Thread listenThread;
bool listenThreadStop;
AddItemCallBack addItemCallBack;
RemoveItemCallBack removeItemCallBack;
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
//自动添加本地ip
string localhost = Dns.GetHostName();
IPAddress[] local_ip = Dns.GetHostAddresses(localhost);
foreach (IPAddress ip in local_ip)
{
comboBox.Items.Add(ip);
}
//实例化回调函数
addItemCallBack = comboBox.Items.Add;
removeItemCallBack = comboBox.Items.Remove;
//实例化一个Socket对象,并开始监听
IPEndPoint Point;
Point = new IPEndPoint(IPAddress.Parse(comboBox_IP.Text), Convert.ToInt16(textBox_Port.Text));
listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(Point);
listenSocket.Listen(10);
//实例化一个线程,用于监听客户端
listenThread = new Thread(new ThreadStart(Listening));
listenThreadStop = false;
listenThread.Start();
//线程的具体内容
private void Listening()
{
while (!listenThreadStop)
{
if (!acceptDone) continue;
acceptDone = false;
listenSocket.BeginAccept(new AsyncCallback(AcceptCallback), listenSocket);
}
listenSocket.Close();
}
//异步连接回调函数
private void AcceptCallback(IAsyncResult ar)
{
acceptDone = true;
if (listenThreadStop) return;
Socket listenSocket = (Socket)ar.AsyncState;
Socket TcpSocket = listenSocket.EndAccept(ar);
string strPoint = TcpSocket.RemoteEndPoint.ToString();
comboBox.Invoke(addItemCallBack, strPoint);
dicSocket.Add(strPoint, TcpSocket);
StateObject state = new StateObject();
state.workSocket = TcpSocket;
while (!listenThreadStop)
{
if (!state.recvDone) continue;
if (state.disconnect) break;
state.recvDone = false;
TcpSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(RecvCallback), state);
}
comboBox.Invoke(removeItemCallBack, TcpSocket.RemoteEndPoint.ToString());
dicSocket.Remove(TcpSocket.RemoteEndPoint.ToString());
TcpSocket.Close();
}
//异步接收回调函数
private void RecvCallback(IAsyncResult ar)
{
if (listenThreadStop) return;
StateObject state = (StateObject)ar.AsyncState;
Socket TcpSocket = state.workSocket;
int count = TcpSocket.EndReceive(ar);
if (count > 0)
TcpSocket.BeginSend(state.buffer, 0, count, 0, null, null);
else
state.disconnect = true;
state.recvDone = true;
}
//用字典实现向指定端口发送数据
string point = comboBox.SelectedItem.ToString();
byte[] sendData = Encoding.UTF8.GetBytes(textBox.Text);
dicSocket[point].BeginSend(sendData, 0, sendData.Length, 0, null, null);
//TCP断开连接
listenThreadStop = true;
总结:同步与异步
-
阻塞性的同步方法是当信号未到来之前会一直呈现成假死的状态。
-
非阻塞性的同步方法是当信号来了,还要自己去完成随后的相应处理。
-
异步方法是当信号来了并且随后的相应处理也结束了,才会去通知调用者。
意义:
- 异步操作可以减轻调用者所在线程的运算负担。(其次)
- 对于在信号到来后需要立刻做处理的情况,如果是同步操作,那么只能是新开一个线程来对信号的到来进行反复的轮询,而对于异步操作来说则可以采用硬件中断的方法来避免新开一个线程的资源。(首要)
- 线程间的切换会对系统产生额外的负担,过多的共享变量可能会导致死锁的出现。(未明)
缺点:Complicated
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!