当前位置:网站首页>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和端口后,点击连接。这时可以看到服务端监测到有有客户端的接入了,这时就可以互相收发数据了,效果如下:
边栏推荐
- LaneATT
- 从哪些维度评判代码质量的好坏?如何具备写出高质量代码的能力?
- IP protocol - network segment division
- torch_ How to use scatter. Scatter() in detail
- 【LeetCode】Day102-螺旋矩阵 II
- Automatic derivation of pytorch
- [TA frost wolf \u may - hundred people plan] Figure 3.4 introduction to delayed rendering pipeline
- G026-db-gs-ins-03 openeuler deployment opengauss (1 active and 2 standby or multiple standby)
- If this.$router Push the same address with different parameters, and the page does not refresh
- Windows10 installation free redis
猜你喜欢

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

LaneATT

Read the paper with me - multi model text recognition network

Which is a good noise reduction Bluetooth headset? Ranking of the most cost-effective noise reduction Bluetooth headsets

狗牙根植物介绍

C - partial keyword

LaneATT

Dynamics crm: how to set the order of forms

Still using listview? Use animatedlist to make list elements move

Leetcode 231. 2 的幂
随机推荐
Leetcode 223. 矩形面积
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
Dedecms editor supports automatic pasting of word pictures
Kubernetes版本对接对象存储
安信证券开户在手机开户安全吗?
What is the ranking of good securities companies? Is online account opening safe
Using JS to implement click events
JUC源码学习笔记3——AQS等待队列和CyclicBarrier,BlockingQueue
[SWT] user defined data table
Experience summary of slow SQL problems
Force button 31. Next arrangement -- double finger needling
Fine tune layoutlm V3 for bill data processing and content recognition
If this.$router Push the same address with different parameters, and the page does not refresh
Class assignment (6) - 575. Word division (word)
Lsyncd搭建同步镜像-用Lsyncd实现本地和远程服务器之间实时同步
Lsyncd 实时同步
矩阵的秩和图像的秩的一些了解
Feign for 20 minutes every day
Please talk about the financial products with a yield of more than 6%
Adaptive design and responsive design