0、背景
本协议包参考车联网TCP 组包格式,C#写测试客户端。
1、代码
主函数
static void Main(string[] args)
{
//TestData.LoginData();
//TestData.PostData();
//Console.ReadLine();
//return;
byte[] re;
MyTcpClient.Connect();
Console.WriteLine("输入任意字符并回车用以发送登录数据 >");
Console.ReadLine();
//send//向服务器端发送消息
re = System.Text.Encoding.ASCII.GetBytes(TestData.LoginData());
//re = StringTool.strToToHexByte(TestData.LoginData());
MyTcpClient.SendMsg(re);
Console.WriteLine("登录发送完毕");
Console.WriteLine("输入任意字符并回车用以发送检测数据 >");
Console.ReadLine();
for(int i = 0; i < 5; i++)
{
//re = StringTool.strToToHexByte(TestData.PostData());
re = System.Text.Encoding.ASCII.GetBytes(TestData.PostData());
MyTcpClient.SendMsg(re);
Thread.Sleep(2000);//不加这个会粘包
}
Console.WriteLine("输入任意字符并回车用以发送检测数据 >");
Console.ReadLine();
//客户端发送消息登出 主动关闭连接
}
Tcp Client
public class MyTcpClient
{
static int defaultPort = 7738;
static string defaultIp = "10.1.31.31";
private static Socket clientSocket = null;
private static Thread thread = null;
/// <summary>
/// 连接服务器端
/// </summary>
public static void Connect()
{
int.TryParse(System.Configuration.ConfigurationManager.AppSettings["serverport"], out defaultPort);
if (false == string.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings["serverip"]))
{
defaultIp = System.Configuration.ConfigurationManager.AppSettings["serverip"];
}
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(defaultIp);
IPEndPoint endPoint = new IPEndPoint(ip, defaultPort);
clientSocket.Connect(endPoint);
thread = new Thread(ReceMsg);
thread.IsBackground = true;
thread.Start();
}
/// <summary>
/// 接收服务器端数据
/// </summary>
private static void ReceMsg()
{
while (true)
{
try
{
byte[] buffer = new byte[1024];
int length = clientSocket.Receive(buffer);
Console.WriteLine("连接状态:" + clientSocket.Connected);
if (clientSocket.Connected == false)
{
return;
}
byte[] buf = new byte[length];
Array.Copy(buffer, buf, length);
Console.WriteLine("接收消息>");
Console.WriteLine(System.Text.Encoding.ASCII.GetString(buf));// StringTool.byteToHexStr(buf));
}catch(SocketException ex)
{
Console.WriteLine(ex.Message);
if (ex.ErrorCode == 10054)
{
return;
}
}
}
}
public static void SendMsg(string msg)
{
clientSocket.Send(Encoding.ASCII.GetBytes(msg));
}
public static void SendMsg(byte[] buffer)
{
clientSocket.Send(buffer);
}
}
组包测试
public class TestData
{
public static string LoginData()
{
string head = StringTool.StringToHexString("##", UTF8Encoding.ASCII);//0 起始符号
string cmd = "";
cmd += "01";//2 命令标识
cmd += "FE";//3 应答标志
cmd += StringTool.StringToHexString("SKYWELLIT00000003", UTF8Encoding.ASCII).ToUpper();//4 唯一识别码 主板程序编号
cmd += "01";//21 数据单元加密方式 01 不加密
string dataLength = ""; //22 数据单元长度 WORD
string data = "";
DateTime dt = DateTime.Now;
data += Convert.ToString(19, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Month, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Day, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Hour, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Minute, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Second, 16).PadLeft(2, '0');
string s2 = Convert.ToString(2001, 16).ToUpper();//登录流水号
s2 = s2.PadLeft(4, '0');
data += s2;
data += StringTool.StringToHexString("898600MFSSYYGXXXXX03", Encoding.ASCII).ToUpper();
data += StringTool.StringToHexString("1", UTF8Encoding.ASCII); //温度
data += StringTool.StringToHexString("1", UTF8Encoding.ASCII); //湿度
data += StringTool.StringToHexString("0", UTF8Encoding.ASCII); //烟雾
data += StringTool.StringToHexString("0", UTF8Encoding.ASCII); //水浸
data += StringTool.StringToHexString("0", UTF8Encoding.ASCII);//电力
data += StringTool.StringToHexString("0", UTF8Encoding.ASCII);//入侵
dataLength = Convert.ToString(data.Length, 16);
Console.WriteLine(dataLength);
dataLength = dataLength.PadLeft(4, '0');
string check = StringTool.GetBCCXorCode(StringTool.strToToHexByte(cmd + dataLength + data));
string s = head + cmd + dataLength + data + check;
return s;
}
public static string PostData()
{
string head = StringTool.StringToHexString("##", UTF8Encoding.ASCII);//0 起始符号
string cmd = "";
cmd += "02";//2 命令标识 01 登录 02 实时信息上报
cmd += "FE";//3 应答标志
cmd += StringTool.StringToHexString("SKYWELLIT00000003", UTF8Encoding.ASCII);//4 唯一识别码 主板程序编号
cmd += "01";//21 数据单元加密方式 01 不加密
string dataLength = ""; //22 数据单元长度 WORD
string data = "";
DateTime dt = DateTime.Now;
data += Convert.ToString(19, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Month, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Day, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Hour, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Minute, 16).PadLeft(2, '0');
data += Convert.ToString(dt.Second, 16).PadLeft(2, '0');
data += "01";
data += Convert.ToString(22).PadLeft(2, '0').PadRight(4,'0'); //温度
data += "02";
data += Convert.ToString(28).PadLeft(2, '0').PadRight(4, '0'); //湿度
dataLength = Convert.ToString(data.Length, 16);
dataLength = dataLength.PadLeft(4, '0');
string check = StringTool.GetBCCXorCode(StringTool.strToToHexByte(cmd + dataLength + data));
string s = head + cmd + dataLength + data + check;
return s;
}
}
public class StringTool
{
/// <summary>
/// 将字符串转为16进制字符,允许中文
/// </summary>
/// <param name="s"></param>
/// <param name="encode"></param>
/// <returns></returns>
public static string StringToHexString(string s, Encoding encode)
{
byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组
string result = string.Empty;
for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符
{
result += Convert.ToString(b[i], 16);
}
return result;
}
/// <summary>
/// 将16进制字符串转为字符串
/// </summary>
/// <param name="hs"></param>
/// <param name="encode"></param>
/// <returns></returns>
public static string HexStringToString(string hs, Encoding encode)
{
string strTemp = "";
byte[] b = new byte[hs.Length / 2];
for (int i = 0; i < hs.Length / 2; i++)
{
strTemp = hs.Substring(i * 2, 2);
b[i] = Convert.ToByte(strTemp, 16);
}
//按照指定编码将字节数组变为字符串
return encode.GetString(b);
}
/// <summary>
/// 将byte[]转为16进制字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string byteToHexStr(byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}
/// <summary>
/// 将16进制的字符串转为byte[]
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
public static byte[] strToToHexByte(string hexString)
{
hexString = hexString.Replace(" ", "");
if ((hexString.Length % 2) != 0)
hexString = "0" + hexString;
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return returnBytes;
}
/// <summary>
/// BCC和校验代码返回16进制
/// </summary>
/// <param name="data">需要校验的数据包</param>
/// <returns></returns>
public static string GetBCCXorCode(byte[] data)
{
byte CheckCode = 0;
int len = data.Length;
for (int i = 0; i < len; i++)
{
CheckCode ^= data[i];
System.Console.WriteLine(data[i]);
}
System.Console.WriteLine(CheckCode);
return Convert.ToString(CheckCode, 16).ToUpper();
}
/// <summary>
/// BCC和校验代码
/// </summary>
/// <param name="data">需要校验的数据包</param>
/// <returns></returns>
public static byte Get_CheckXor(byte[] data)
{
byte CheckCode = 0;
int len = data.Length;
for (int i = 0; i < len; i++)
{
CheckCode ^= data[i];
}
return CheckCode;
}
}