TCP通信
程序员文章站
2022-03-04 08:48:38
...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using TcpProto;
using System.Diagnostics;
namespace NewRemoteClient.ganjie
{
class SocketSingleInstance
{
public static Socket socketClient = null; //连接套接字
public static Thread threadClient = null; //接受消息线程
public static Thread heartBeatThread = null; //心跳包线程
public static Thread MsgDealThread = null; //遍历字典
public const int SendBufferSize = 2 * 1024;
public const int ReceiveBufferSize = 4 * 1024;
#region typeID
public static int tcp_confirmID = 0x1001; //返回监控端认证ID
public static int tcp_imginfor = 0x2004; //pic信息
public static int tcp_sreport = 0x3003; //接受重传Repost-infor
#endregion
public static byte[] Length = new byte[4]; //长度
public static byte[] typeID = new byte[4]; //typeID
public IMessage message { get; set; }
//public object PackageAnl { get; private set; }
public bool connectCheck = false;
private int heartNum = 0;
private static volatile SocketSingleInstance instance;
private static readonly object locker = new object();
private SocketSingleInstance() { }
/// <summary>
/// 单例返回判断
/// </summary>
/// <returns></returns>
public static SocketSingleInstance GetInstance()
{
lock (locker)
{
if (instance == null)
{
instance = new SocketSingleInstance();
}
}
return instance;
}
/// <summary>
/// 连接服务器
/// </summary>
public void ConnectToServer(string ip, int port)
{
try
{
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddress = IPAddress.Parse(ip);
IPEndPoint endport = new IPEndPoint(ipaddress, port);
socketClient.Connect(endport);
Console.WriteLine("已与服务器连接,可以开始通信...\r\n");
}
catch (Exception ex)
{
Console.WriteLine("error+" + ex.ToString());
}
if (socketClient.Connected)
{
Console.WriteLine("++++连接服务器成功!");
connectCheck = true;
}
}
/// <summary>
/// 客户端接受消息
/// </summary>
public void ReceiveServerMsg()
{
int cheknum = 0;
while (true)
{
if (connectCheck)
{
try
{
if (heartNum > 3)
{
if (cheknum < 3)
connectCheck = false;
else if (cheknum > 0)
connectCheck = true;
}
byte[] res = new byte[4];
var length1 = socketClient.Receive(res);
Console.WriteLine("TCP信息返回:{0}", length1);
int data = BitConverter.ToInt32(res, 0) - 4;
Console.WriteLine("TCP信息返回:{0}", data);
byte[] proto = new byte[data];
var length2 = socketClient.Receive(typeID, 4, SocketFlags.None);
int typeid = BitConverter.ToInt32(typeID, 0);
Console.WriteLine("TCP信息返回ID:{0}", typeid);
var length3 = 0;// socketClient.Receive(proto, start, data, SocketFlags.None);
while (length3 < data - 1)
{
length3 += socketClient.Receive(proto, length3, data - length3, SocketFlags.None);
}
if (length3 == data)
{
message = PackageAnl.Ap_first(proto, typeid);
}
Console.WriteLine("receive successful");
if (typeid == ProtoId.srepc_confirm)
{
//Thread heartbeat = new Thread(Heart);
//heartbeat.IsBackground = true;
//heartbeat.Start();
UISource.UiButton = 7;
UISource.UiButtonCheck = true;
Thread t = new Thread(new ThreadStart(work));
t.Start();
}
else if (typeid == ProtoId.srepc_heart)
{
Console.WriteLine("heartbeat receive");
cheknum++;
}
Thread.Sleep(20);
}
catch (Exception recieve)
{
Console.WriteLine("ReceiveServerMsg接收错误:\t" + recieve.Message);
connectCheck = false;
}
}
}
}
/// <summary>
/// 心跳包发送
/// </summary>
private void Heart()
{
if (connectCheck)
{
int Setypeid = ProtoId.creq_heart;
creq_heart mreq_heart = new creq_heart
{
Heart = new Heartbeat
{
Timestamp = (int)GetCurrentTimeUnix()
}
};
Console.WriteLine("send heartbeat");
sendMsg(mreq_heart, Setypeid);
heartNum++;
//Thread.Sleep(30 * 1000);
}
}
public int sendMsg(IMessage msg, int typeid)
{
try
{
int length = 4 + msg.CalculateSize();
Length = BitConverter.GetBytes(length);
byte[] bmsg = new byte[length + 4];
typeID = BitConverter.GetBytes(typeid);
byte[] proto = msg.ToByteArray();
//byte[] proto = msg.ToByteString(). ToByteArray();
bmsg = ListTest(Length, typeID, proto);
socketClient.Send(bmsg, bmsg.Length, SocketFlags.None);
Console.WriteLine("send successful\n");
return 0;
}
catch (Exception send)
{
Console.WriteLine("发送错误:\t" + send.Message);
return 0;
}
}
public byte[] ListTest(byte[] first, byte[] second, byte[] thrid)
{
List<byte> byteSource = new List<byte>();
Stopwatch sw = new Stopwatch();
sw.Start();
byteSource.AddRange(first);
byteSource.AddRange(second);
byteSource.AddRange(thrid);
byte[] data = byteSource.ToArray();
sw.Stop();
Console.WriteLine("ListTest " + sw.ElapsedMilliseconds + " 毫秒,数组长度:" + data.Length);
return data;
}
/// <summary>
/// 监控端发送认证信息
/// </summary>
public void tcpSendMreqConfirm()
{
mreq_confirm mcfm = new mreq_confirm
{
Confirm = new Confirm
{
MagicNum = 1
}
};
sendMsg(mcfm, ProtoId.mreq_confirm); //发送
threadClient = new Thread(ReceiveServerMsg);
threadClient.IsBackground = true;
threadClient.Start();
}
/// <summary>
/// 受控端发送认证信息
/// </summary>
public void tcpSendcreqConfirm()
{
creq_confirm mcfm = new creq_confirm
{
Confirm = new Confirm
{
MagicNum = 1
}
};
sendMsg(mcfm, ProtoId.creq_confirm); //发送
threadClient = new Thread(ReceiveServerMsg);
threadClient.IsBackground = true;
threadClient.Start();
//Thread tcpcheck = new Thread(tcpconnectCheck);
//tcpcheck.IsBackground = true;
//tcpcheck.Start();
}
/// <summary>
/// 监测远程连接并重新初始化
/// </summary>
private void tcpconnectCheck()
{
while (true)
{
if (!connectCheck)
{
//socketClient.Disconnect(true);
tcpSendcreqConfirm();
}
else
Console.WriteLine("process goes on");
Thread.Sleep(50 * 1000);
}
}
/// <summary>
/// 监测远程连接并重新初始化
/// </summary>
private void work()
{
Heart();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 60 * 1000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
timer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Console.WriteLine("Test");
Heart();
}
/// <summary>
/// 获取时间戳
/// </summary>
/// <returns></returns>
private static long GetCurrentTimeUnix()
{
TimeSpan cha = (DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)));
long t = (long)cha.TotalSeconds;
Console.WriteLine("时间戳:\t" + t.ToString());
return t;
}
/// <summary>
/// 关闭tcp长连接
/// </summary>
public void Close()
{
socketClient.Disconnect(false);
socketClient.Dispose();
instance = null;
}
public delegate void ChangeLoginStatus(bool logStatus);
public static event ChangeLoginStatus loginStatus;
}
}
下一篇: php限制文件上传类型的方法
推荐阅读