C# Socket之异步TCP客户端断线重连

Stella981
• 阅读 952

  我们知道TCP通信是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低,它首先需要服务端开启服务,然后客户端才可以去连接,如果服务端没有开启通信服务或者连接之后再中途因为某些原因断开连接了,那么都是会通信失败的,所以我们这篇博客主要是对TCP通信加入两个机制。1,客户端开启后未连接成功,自动重连请求 2,若通信途中因为某些原因断开连接了自动重连机制  因为测试发现如果是程序运行途中我们利用同步的方式重新连接的话连接时会出现程序卡顿的情况,这个对用户的体验是非常不好的,为了避免这个情况,我们采用的是异步TCP通信的方式,代码如下,这是一个单例脚本,无需挂载,程序开始时调用一下ConnectServer方法开启通信就好,记得关闭程序时要调用一下Close方法来断开挂起的异步连接,否则调试的时候通信会一直保存着。

/***********************************
*    Description:异步TCP客户端
*    Mountpoint:这是一个单例脚本,无需挂载,直接调用即可
*    Date:2019.06.25
*    Version:unity版本2017.2.0f3
*    Author:LJF
***********************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System;
using System.Text;


namespace LJF
{
    //规范命名、添加注释、合理封装、限制访问权限    
    public class AsyncTcpClient 
    {
        private string ip1;
        private int port1;
        byte[] ReadBytes = new byte[1024 * 1024];
        //单例
        public static AsyncTcpClient Instance
        {
            get
            {
                if (instance==null)
                {
                    instance = new AsyncTcpClient();
                }
                return instance;
            }
        }
        private static AsyncTcpClient instance;

        System.Net.Sockets.TcpClient tcpClient;
       
        //连接服务器
        public void ConnectServer(string ip, int port)//填写服务端IP与端口
        {
            //Debuger.EnableSave = true;
            ip1 = ip;
            port1 = port;
            try
            {
                tcpClient = new System.Net.Sockets.TcpClient();//构造Socket
                tcpClient.BeginConnect(IPAddress.Parse(ip), port,Lianjie, null);//开始异步
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
            }
        }
      
        //连接判断
        void Lianjie(IAsyncResult ar)
        {
            if (!tcpClient.Connected)
            {
                Debug.Log("服务器未开启,尝试重连。。。。。。");
                tcpClient.BeginConnect(IPAddress.Parse(ip1), port1, Lianjie, null);
                //IAsyncResult rest = tcpClient.BeginConnect(IPAddress.Parse(ip1), port1, Lianjie, null);
                //bool scu= rest.AsyncWaitHandle.WaitOne(3000);
            }
            else
            {
                Debug.Log("连接上了");
                tcpClient.EndConnect(ar);//结束异步连接
                tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
            }
        }

       
        //接收消息
        void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                int len = tcpClient.GetStream().EndRead(ar);//结束异步读取
                if (len > 0)
                {
                    
                    string str = Encoding.UTF8.GetString(ReadBytes, 0,len);
                    str = Uri.UnescapeDataString(str);
                    //将接收到的消息写入日志
                    //Debuger.Log(string.Format("收到主机:{0}发来的消息|{1}", ip1, str));
                    //Debug.Log(str);
                    tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
                }
                else
                {
                    tcpClient = null;
                    Debug.Log("连接断开,尝试重连。。。。。。");
                    ConnectServer(ip1,port1);
                }
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
            }
        }

        //发送消息
        public void SendMsg(string msg)
        {
            byte[] msgBytes = Encoding.UTF8.GetBytes(msg);
            tcpClient.GetStream().BeginWrite(msgBytes, 0, msgBytes.Length, (ar) => {
                tcpClient.GetStream().EndWrite(ar);//结束异步发送
            }, null);//开始异步发送
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Close()
        {
            if (tcpClient != null && tcpClient.Client.Connected)
                tcpClient.Close();
            if (!tcpClient.Client.Connected)
            {
                tcpClient.Close();//断开挂起的异步连接
            }
        }

    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java学习 网络编程 tcp
有客户端和服务端,使用tcp传输day26 27//客户端发数据到服务端/\\Tcp传输,客户端建立的过程。\1,创建tcp客户端socket服务。使用的是Socket对象。\建议该对象一创建就明确目的地。要连接的主机。\2,如果连接建立成功,说明数据传输通道已建立。\该通道就是socket流
Stella981 Stella981
3年前
Android Socket 通信
Androidsocket通信安卓编写Socket客户端,实现连接Socket服务端通信。创建Socket连接并获取服务端数据先创建几个全局变量吧privateBufferedWriterwriternull;Socketsocket;
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
CC3200在AP模式的TCP sock作为客户端连接时返回SL_ECONNREFUSED(
1\.CC3200处于AP模式(电脑无线连接CC3200的WIFI信号),开启一个TCPsocket,这个socket作为TCP客户端去连接TCP服务器端structsockaddr_inaddr;unsignedlongg_ulDestinationIp;longlRetVal1;
Wesley13 Wesley13
3年前
34.TCP取样器
阅读文本大概需要3分钟。1、TCP取样器的作用   TCP取样器作用就是通过TCP/IP协议来连接服务器,然后发送数据和接收数据。2、TCP取样器详解!(https://oscimg.oschina.net/oscnet/32a9b19ba1db00f321d22a0f33bcfb68a0d.png)TCPClien
Stella981 Stella981
3年前
Socket心跳机制
本文是我在实际工作中用到的Socket通信,关于心跳机制的维护方式,特意总结了一下,希望对朋友们有所帮助。Socket应用:首先Socket封装了tcp协议的,通过长连接的方式来与服务器通信,是由服务器和客户端两部分组成的,当客户端成功连接之后,服务器会记录这个用户,并为它分配资源,当客户端断开连接后,服务器会自动释放资源。但在实际的网络环
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这