当前位置:网站首页>C# TCP客户端窗体应用程序异步接收方式
C# TCP客户端窗体应用程序异步接收方式
2022-07-24 15:55:00 【luobeihai】
1. 程序界面设计
大概设计一个如下的简单界面。![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rq7GgnZv-1658637960222)(../picture/image-20220724124105799.png)]](/img/90/ad1f30d81e630460d9284efecbb9e5.png)
2. 各部分核心代码
2.1连接服务端
当请求连接按钮按下时,会触发点击事件,然后进行连接服务端请求。
private void btnConnect_Click(object sender, EventArgs e)
{
try
{
if (IsConnected == false)
{
tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 创建一个Socket套接字
IPAddress ipaddress = IPAddress.Parse(cbbHostIP.Text);
EndPoint point = new IPEndPoint(ipaddress, int.Parse(tbHostPort.Text));
tcpClient.Connect(point);
tcpClient.BeginReceive(recieveBuffer, 0, recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
IsConnected = true;
btnConnect.Text = "断开连接";
}
else
{
tcpClient.Disconnect(false);
IsConnected = false;
btnConnect.Text = "请求连接";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
按下连接时,先创建一个socket套接字,然后从控件中获得用户输入的服务端IP和端口,然后进行连接。
最重要的是,这里进行了异步接收设计,设置了接收回调函数 ReceiveCallback。
2.2 发送数据
因为发送数据,是用户主动按下“发送”按钮发送的,所以比较简单,只要有按下发送按钮的点击事件,就发送数据。
private void btnSend_Click(object sender, EventArgs e)
{
if (IsConnected == true)
{
tcpClient.Send(tbSend.Text.GetBytes("GBK"));
}
else
{
MessageBox.Show("请先连接服务端");
}
}
2.3 接收数据
接收数据采用异步接收方式,因为无法确定服务端什么时候会发送数据给客户端。
private void ReceiveCallback(IAsyncResult AR)
{
// Check how much bytes are recieved and call EndRecieve to finalize handshake
try
{
int recieved = tcpClient.EndReceive(AR);
if (recieved <= 0)
return;
string message = Encoding.GetEncoding("GBK").GetString(recieveBuffer, 0, recieved); // 只将接收到的数据进行转化
Print(message);
// Start receiving again
tcpClient.BeginReceive(recieveBuffer, 0, recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
}
其中,ReceiveCallback 函数是接收的回调函数。如果有数据接收,那么真正接收数据的处理过程,是在这个回调函数完成的。
3. 整个工程源码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
namespace Net_assistance
{
public partial class Form1 : Form
{
public static Socket tcpClient;
bool IsConnected = false;
private byte[] recieveBuffer = new byte[8142];
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_Load(object sender, EventArgs e)
{
// 获取本地可用的IP地址
string strHostIP = Dns.GetHostName();
IPAddress[] ipadrlist = Dns.GetHostAddresses(strHostIP);
foreach (IPAddress ipaddr in ipadrlist)
{
if (ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
cbbHostIP.Items.Add(ipaddr.ToString());
}
cbbHostIP.Items.Add("127.0.0.1"); // 最后加上回环测试地址
cbbHostIP.SelectedIndex = 0;
tbHostPort.Text = "8080";
tbSend.Text = "hello world!";
}
private void Print(string msg)
{
tbRecv.AppendText($"[{
DateTime.Now.ToString("yyy-MM-dd HH.mm.ss.fff")}] {
msg}\r\n");
}
private void ReceiveCallback(IAsyncResult AR)
{
// Check how much bytes are recieved and call EndRecieve to finalize handshake
try
{
int recieved = tcpClient.EndReceive(AR);
if (recieved <= 0)
return;
string message = Encoding.GetEncoding("GBK").GetString(recieveBuffer, 0, recieved); // 只将接收到的数据进行转化
Print(message);
// Start receiving again
tcpClient.BeginReceive(recieveBuffer, 0, recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnConnect_Click(object sender, EventArgs e)
{
try
{
if (IsConnected == false)
{
tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 创建一个Socket套接字
IPAddress ipaddress = IPAddress.Parse(cbbHostIP.Text);
EndPoint point = new IPEndPoint(ipaddress, int.Parse(tbHostPort.Text));
tcpClient.Connect(point);
tcpClient.BeginReceive(recieveBuffer, 0, recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
IsConnected = true;
btnConnect.Text = "断开连接";
}
else
{
tcpClient.Disconnect(false);
IsConnected = false;
btnConnect.Text = "请求连接";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnSend_Click(object sender, EventArgs e)
{
if (IsConnected == true)
{
tcpClient.Send(tbSend.Text.GetBytes("GBK"));
}
else
{
MessageBox.Show("请先连接服务端");
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (IsConnected == true)
{
// 关闭窗口时,如果正在连接着服务端,那么断开连接后再退出
tcpClient.Disconnect(false);
}
}
}
}
4. 测试
先用网络调试助手打开一个服务端。如下:
然后打开我们自己写的客户端程序,输入服务端的IP和端口后,点击连接。这时可以看到服务端监测到有有客户端的接入了,这时就可以互相收发数据了,效果如下:
边栏推荐
- G026-db-gs-ins-03 openeuler deployment opengauss (1 active and 2 standby or multiple standby)
- 未来数据库需要关心的硬核创新
- Dynamics crm: sharing records for users and teams
- Read the paper with me - multi model text recognition network
- kubernetes GPU的困境和破局
- mysql源码分析——索引的数据结构
- [SWT] scrolling container to realize commodity list style
- [Luogu] p1908 reverse sequence pair
- 收益率在百分之六以上的理财产品,请说一下
- Simplified understanding: publish and subscribe
猜你喜欢

Leetcode 231. 2 的幂

Memorythrashing: Tiktok live broadcast to solve memory dithering practice

Mlx90640 infrared thermal imager temperature measurement module development notes (III)

聊聊C指针

从哪些维度评判代码质量的好坏?如何具备写出高质量代码的能力?

【着色器实现Pixelate马赛克效果_Shader效果第七篇】

Still using listview? Use animatedlist to make list elements move

YOLO5Face:为什么要重新发明人脸检测器

Withdrawal of IPO application, Yunzhou intelligent "tour" of unmanned boat enterprise fails to enter the science and Technology Innovation Board
![Dynamics crm: [problem solved]cannot open SQL encryption symmetric key because symmetric key password](/img/ae/125fcb16c9d85714c7bbd1255d1d18.png)
Dynamics crm: [problem solved]cannot open SQL encryption symmetric key because symmetric key password
随机推荐
公钥私钥传输,以及对CA证书的理解
机器学习笔记 - 构建推荐系统(5) 前馈神经网络用于协同过滤
[adaptiveavgpool3d] pytorch tutorial
R language ggplot2 visualization: ggplot2 visualization basic scatter plot, through in theme_ Specify the parameter base in BW_ Size to change the size of axis labels and control the size of gridlines
Reentrantlock reentrant lock
20. Shell programming variables
自适应设计和响应式设计
LaneATT
Introduction to single chip microcomputer: LED lights cycle to the left and turn on
What is the ranking of good securities companies? Is online account opening safe
Do you understand the working principle of gyroscope?
JUC源码学习笔记3——AQS等待队列和CyclicBarrier,BlockingQueue
图像label处理——json文件转化为png文件
MySQL之知识点(十二)
Leetcode 220. duplicate element III exists
Simplified understanding: publish and subscribe
Scala functions and their higher-order applications
What is a firewall? What role can firewalls play?
[SWT] user defined data table
Dynamics 365: how to get the threshold value of executemullerequest in batch requests