TcpClient类异步接收数据

TcpClient为基于Socket构建的用来进行TCP通信的简单类,主要用于TCP客户端的编写,可以使用同步或者异步。发送接收数据用NetworkStream。很多东西摘录自MSDN

构造函数

名称说明
TcpClient()初始化 TcpClient 类的新实例。
TcpClient(AddressFamily)使用指定的族初始化 TcpClient 类的新实例。
TcpClient(IPEndPoint)初始化 TcpClient 类的新实例,并将其绑定到指定的本地终结点。
TcpClient(String, Int32)初始化 TcpClient 类的新实例并连接到指定主机上的指定端口。

以上是摘自MSDN上的,其中AddressFamily指的是使用指定的协议族,例如IPv4或者IPv6
如果要指定本地端口,用IPEndPoint来进行绑定。

属性

TcpCient

名称说明
Active获取或设置一个值,该值指示是否已建立连接。
Client获取或设置基础 Socket。
Connected获取一个值,该值指示 TcpClient 的基础 Socket 是否已连接到远程主机。

NetworkStream

名称说明
CanRead获取一个值,该值指示 NetworkStream 是否支持读取
CanWrite获取一个值,该值指示 NetworkStream 是否支持写入

主要方法

TcpClient

名称说明
BeginConnect(IPAddress, Int32, AsyncCallback, Object)开始一个对远程主机连接的异步请求。远程主机由 IPAddress 和端口号 (Int32) 指定。
Close()释放此 TcpClient 实例,并请求关闭基础 TCP 连接。

NetworkStream

名称说明
BeginRead(Byte[], Int32, Int32, AsyncCallback, Object)从 NetworkStream 开始异步读取。
Close()关闭当前流并释放与之关联的所有资源
BeginWrite(Byte[], Int32, Int32, AsyncCallback, Object)开始向流异步写入

流程

TcpClient读取数据过程

TcpClient连接

Created with Raphaël 2.1.0 主线程 实例化TcpClient,可绑定本地端口 异步连接到目标IP和端口(BeginConnect) 结束

TcpClient已经连接上,NetworkStream读取

Created with Raphaël 2.1.0 TcpClient异步连接线程 还原TcpClient 获取NetworkStream NetworkStream可读 NetworkStream异步读取Buffer 异步结束 yes no

NetworkStream已经读取完毕,取出数据

Created with Raphaël 2.1.0 NetworkStream异步读取线程 还原异步读取Buffer 获取Buffer数据 下一次异步读取开启 异步读取结束

TcpClient发送数据流程

确保TcpClient已经连接的情况下执行

TcpClient线程

Created with Raphaël 2.1.0 TcpClient发送 取得NetworkStream 获得数据,异步发送BeginWrite 发送结束

NetworkStream异步发送线程

Created with Raphaël 2.1.0 NetworkStream异步发送 还原NetworkStream 结束发送

实例

TcpClient连接

private void TcpButton_Click(object sender, EventArgs e)
{
    if (TcpButton.Text == "TCP打开")
    {
        TcpButton.Text = "TCP关闭";
        IPEndPoint targetPoint = new IPEndPoint(TcpUdp.VerifyInputIP(IPTextBox.Text), TcpUdp.VerifyInputPort(TcpTargetPortTextBox.Text));
        int localTcpPort = Int32.Parse(TcpSourcePortTextBox.Text);
        if (localTcpPort > 0)
        {
            IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), localTcpPort);
            tcp = new TcpClient(localEP);

        }
        else
        {
            tcp = new TcpClient();
        }
        tcp.ReceiveTimeout = 10;
        //异步连接
        tcp.BeginConnect(IPAddress.Parse(IPTextBox.Text), TcpUdp.VerifyInputPort(TcpTargetPortTextBox.Text), Connected, tcp);
    }
    else
    {
        TcpButton.Text = "TCP打开";
        if ((tcp != null) && (tcp.Connected))
        {
            ns.Close();
            tcp.Close();
        }
        SetTcpPic(tcp.Connected);
        TcpIsOpen = tcp.Connected;
    }
}

NetworkStream异步读取

private void Connected(IAsyncResult iar)
{
    tcp = (TcpClient)iar.AsyncState;
    tcp.EndConnect(iar);
    //MessageBox.Show("connected");
    SetTcpPic(tcp.Connected);
    TcpIsOpen = tcp.Connected;
    if ((tcp != null) && (tcp.Connected))
    {
        ns = tcp.GetStream();

        StateObject state = new StateObject();
        state.client = tcp;
        NetworkStream stream = state.client.GetStream();
        if (stream.CanRead)
        {
            byte[] buffer = new byte[tcp.ReceiveBufferSize];
            stream.BeginRead(state.buffer, 0, StateObject.BufferSize, new AsyncCallback(AsyncReadCallBack), state);
        }
    }
}

NetworkStream读取处理

private void AsyncReadCallBack(IAsyncResult iar)
{
    StateObject state = (StateObject)iar.AsyncState;
    if ((state.client == null) || (!state.client.Connected)) return;
    int NumOfBytesRead;
    NetworkStream ns = state.client.GetStream();
    NumOfBytesRead = ns.EndRead(iar);
    if (NumOfBytesRead > 0)
    {
        byte[] buffer = new byte[NumOfBytesRead];
        Array.Copy(state.buffer, 0, buffer, 0, NumOfBytesRead);
        ReceiveAppend(buffer, TcpUdp.StringType.String);
        ns.BeginRead(state.buffer, 0, StateObject.BufferSize, new AsyncCallback(AsyncReadCallBack), state);
    }
    else
    {
        ns.Close();
        state.client.Close();
        ns = null;
        state = null;
    }
}

NetworkStream发送

if (TcpIsOpen)
{
    if (ns != null)
    {
        //ns.Write(buffer, 0, buffer.Length);
        ns.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(StreamWriteCallBack), ns);
    }
}
private void StreamWriteCallBack(IAsyncResult iar)
{
    NetworkStream ns = (NetworkStream)iar.AsyncState;
    ns.EndWrite(iar);
}
  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
SanNiuSignal是一个基于异步socket的完全免费DLL;它里面封装了Client,Server以及UDP;有了这个DLL;用户不用去关心心跳;粘包 ;组包;发送文件等繁琐的事情;大家只要简单的几步就能实现强大的通信系统;能帮助到大家是本人觉得最幸福的事情,也希望大家 在用的过程中找出DLL中不足的地方;好改正;此DLL的苹果版和java版正在努力开发中......交流QQ:365368248;此演示源码下载地址:http://pan.baidu.com/s/1eQw1npw 里面包括了SanNiuSignal.DLL 下面为大家介绍一下 如何使用SanNiuSignal. 1 ) :TCPServer服务器,通过静态方法TxStart.startServer注册成功服务器ITxServer;然后通过ITxServer设置好各种属性;最后启动 ITxServer.StartEngine();就可以了;具体可以到demo里去看;相对来说比较简单,下面来说一下需要注意的地方 一:ITxServer.BufferSize,就是接收数据缓冲区大小;默认为1kb,不要小于50字节,而且要和客户端设置成一样;否则会出现不可预知 的错误;这个缓冲区的大小,不会影响你每次发送数据的大小;大小只能提高你的发送速度 二:ITxServer.sendMessage 发送前先判断此IPEndPoint客户端是否在线;因为如果不在线等情况发生;此方法没有任何消息产生;如 果发送成功并且对方已经收到;会触发发送成功的事件; 三:用户可以通过ITxServer.FileLog记录服务器的运行信息; 2 ) :TCPClient客户端,通过静态方法TxStart.startClient(服务器地址或网址, 服务器端口号)注册成功客户端ITxClient;然后通过 ITxClient设置好各种属性;最后启动ITxClient.StartEngine();跟服务器启动差不多;具体可以到demo里去看;客户端要注意的一些地 方 一:如果非服务器强制关闭客户端的情况下,掉线的话,客户端默认是要重连的;他的原理是这样的,每10秒重连一次;重连 ITxClient.ReconnectMax次如果失败;会自动关闭客户端引擎;在重连的过程中;你可以改变客户端连接服务器的IP地址和端口号;但 如果当断开的时候不想重连;可以设置ITxClient.ReconnectMax=0; 二:登录篇,在引擎启动之前,用户可以设置ITxClient.OutTime来设置超时时间;默认为10秒,也就是说10秒之内肯定会有一个登录结果 ;登录成功或登录失败。有了登录结果会触发登录结果事件; 3 ) :Udp引擎,通过静态方法TxStart.startUdp()注册成功UDP--IUdpTx;然后通过IUdpTx设置好各种属性;最后启动 IUdpTx.StartEngine();如果在启动之前要绑定端口号,请在这里设置IUdpTx.Port;否则是随机使用本地端口;无论是UDP还是服务器和 客户端;它们的很多方法和属性以及事件都是相同的,因为他们都继承了通信系统的基接口ITxBase;下面是UDP引擎要注意的地方 一:UDP的优势在于速度快但不太可靠;所以有些属性不能设置的太过,如IUdpTx.BufferSize;默认为1KB,如果在广域网上发送信息, 缓冲区大小不要超过默认值;否则数据会丢失,如果一次性数据大于1KB;也没事,系统会自动分包发送;不太会丢包。 4 ) :文件发送系统,通过静态方法FileStart.StartFileSend(IFileSendMust)生成一个文件发送系统IFileSend;其中IFileSendMust是 必须实现的一个接口;具体参照demo;然后通过IFileSend设置好各种属性;发送还是要通过前面的三个引擎系统发送的;如 ITxClient.SendFile 这时会返回一个文件标签,是一个整数;IFileSend可以通过操作这个标签来操作这个正在发送的文件;接收文件 系统也一样;也是通过文件标签来操作;文件续传也是一样,也要通过前面的三个通信引擎系统进行续传;因为文件系统不能决定用户 通过哪个通信系统进行续传的;例如IUdpTx.ContinueFile进行续传;大家也可以试一下 掉线之后重新连接也可以续传; 5 ) :文件接收系统,通过静态方法FileStart.StartFileReceive(IFileReceiveMust)生成一个文件接收系统IFileReceive;其中 IFileReceiveMust是接收方必须实现的一个接口;具体参照demo;然后通过IFileReceive设置好各种属性;下面来讲讲文件系统要注意 的几个要点 一:每个文件都有一个文件标签,发送系统和接收系统是通过控制这个标签来控制这个文件的;如果是同一个文件传输,标签也一样的; 二:要注意属性BufferSize缓冲区大小,他是代表一次传送的字节数;如果这个文件缓冲区越大,传输速度越快;具体要设置成多少,大 家自己去调试;TCP传输的话一般可以设置成比较大,但UDP的话这个不要超过1KB;所以传输大文件尽量不要用UDP这种不可靠的东东; 三:当网络等各种原因中断文件的时候;会触发文件中断事件;文件自动处于暂停发送或接收状态;等待续传;续传的发送方,如果对方 同意续传;对方将不会触发续传开始的方法;别的大家可以通过demo里去发现; 总结: 其实这个DLL相对来讲是比较简单的;大家只要掌握这五个接口;1:ITxServer TCP服务器接口 2:ITxClient TCP客户端接口 3:IUdpTx UDP接口 4:IFileSend 文件发送方接口 5:IFileReceive 文件接收方接口 前面三个接口是通过TxStart启动;后面二个文件接口 是通过FileStart启动 今天先讲到这里;希望这个DLL对大家有所帮助;不足之处希望通过QQ或博客园大家一起交流;谢谢 此演示源码下载地址:http://pan.baidu.com/s/1eQw1npw 里面包括了SanNiuSignal.DLL
C#中的异步TCPClient是一种用于进行网络通信的。它允许你在进行网络连接、发送和接收数据时,使用异步操作来提高应用程序的性能和响应性。 要使用异步TCPClient,你需要使用C#的异步编程模型(Async/Await)。以下是使用异步TCPClient的一些基本步骤: 1. 创建一个TCPClient对象,并指定要连接的远程主机和端口号。 2. 使用TCPClient对象的ConnectAsync方法,以异步方式连接到远程主机。 3. 一旦连接成功,你可以使用TCPClient对象的GetStream方法获取与远程主机进行通信的网络流。 4. 对于发送数据,你可以使用网络流的WriteAsync方法以异步方式发送字节数据或字符串。 5. 对于接收数据,你可以使用网络流的ReadAsync方法以异步方式接收字节数据或字符串。 下面是一个简单的示例代码,展示了如何使用异步TCPClient发送和接收数据: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; public class AsyncTcpClient { public static async Task Main() { // 远程主机的IP地址和端口号 string ipAddress = "127.0.0.1"; int port = 12345; // 创建TCPClient对象并连接到远程主机 TcpClient client = new TcpClient(); await client.ConnectAsync(IPAddress.Parse(ipAddress), port); // 获取与远程主机进行通信的网络流 NetworkStream stream = client.GetStream(); // 发送数据 string messageToSend = "Hello, server!"; byte[] sendData = Encoding.UTF8.GetBytes(messageToSend); await stream.WriteAsync(sendData, 0, sendData.Length); // 接收数据 byte[] receiveData = new byte

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值