发送保护服务器与合并器的通讯协议。模拟正弦曲线。电力
模拟正弦曲线操作。以及相关的数组方面的操作。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Net;
using System.Net.Sockets;
namespace 微妙

{
class Program
{
const int shuLiang = 63;

测时间 API函数#region 测时间 API函数
[DllImport("kernel32.dll")]
private static extern bool QueryPerformanceFrequency(ref Int64 lpFrequency);
[DllImport("kernel32.dll")]
private static extern bool QueryPerformanceCounter(ref Int64 lpPerformanceCount);
#endregion 
public static void Main(string[] args)
{
byte[] myByte1 = new byte[109];
byte[] myByte2 = new byte[17];

输入#region 输入
Console.WriteLine("输入发送帧的数量。1s发送400次");
int num =Convert .ToInt32(Console.ReadLine());
Console.WriteLine("输入每发送一个帧的间隔(每发送1次延时)控制每发送一个帧用的时间为1/400s,大约为1000000");
int time = Convert.ToInt32(Console.ReadLine());
#endregion 

udp发送设置#region udp发送设置
//初始化一个Scoket实习,采用UDP传输
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress ip = IPAddress.Parse("192.168.137.110");
//初始化一个发送广播和指定端口的网络端口实例
IPEndPoint iep = new IPEndPoint(ip, 3000);
//设置该scoket实例的发送形式
sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
#endregion

计时#region 计时
long frequency = 0;
if (!QueryPerformanceFrequency(ref frequency))
{
Console.WriteLine("不支持!");
return;
}
long start = 0;
if (!QueryPerformanceCounter(ref start))
{
Console.WriteLine("开始查询失败!");
return;
}
#endregion

发送#region 发送
//int num = 0;
for (int j = 0; j < num; j++)
{
myByte1 = MyByte(j);
sock.SendTo(myByte1,iep);
//时间控制
ShiJianKongZhi(time);
if (j % 400 == 0)
{
myByte2 = ZhiLiuLiang(num);
sock.SendTo(myByte2, iep);
}
}
#endregion

计时结果。每个udp包的发送时间#region 计时结果。每个udp包的发送时间
long end = 0;
if (!QueryPerformanceCounter(ref end))
{
Console.WriteLine("查询结束失败!");
return;
}
Console.WriteLine("频率={0},平均发送时间(每个设备每个udp包):{1}",
frequency, (double)(end - start) / (((double)frequency) * num));
sock.Close();
#endregion 
Console.ReadKey();
}

/**//// <summary>
/// 控制时间
/// </summary>
static void ShiJianKongZhi(int time)
{
int num=0;
for (int i = 0; i < time; i++)
{
num++;
}
}

/**//// <summary>
/// 生成数组遥测数据帧
/// </summary>
static byte[] MyByte(int num)
{
Random rd = new Random();
byte [] myByte=new byte [109];
//设备号。共1-63个依次发送,其中0号保留
myByte[0] = (byte)(num % shuLiang + 1);
//标志位/计数位,低6位表示本毫秒内的先后顺序
myByte[1] = (byte)rd.Next(0, shuLiang);
//状态:占用2个字节,高4位恒为0,无意义。低12位依据实际情况标识,对应二进制位为1采数据,为0不采数据
//这里表示为12路都采集
myByte[2] = (byte)15;
myByte[3] = (byte)127;
//bo表示是第几次发送。在一个周波内采集32次,一共分为32/4次发送。
int bo = num / shuLiang % 8;
//标记循环中数组的维数
int xunHuan = 0;
for (int i = 0; i < 4; i++)
{
//其中360/8表示把360度分为了八份,每份占多少度。360/32代表360度分为了32份。
//(360/32)*i代表在八份里再分为四份。
double angleX = Math.PI * ((360/8)*bo+(360/32)*i) / 180.0;
//把正弦曲线整体的往上移动。其中峰值设为30000(90度).最低为0(270度)
int boZhi = (int)((Math.Sin(angleX) + 1) * 15000);
for (int j = 0; j < 13; j++)
{
if (j < 12)
{
myByte[4 + xunHuan] = (byte)((boZhi + rd.Next(0, 500)) / 128);
xunHuan++;
myByte[4 + xunHuan] = (byte)((boZhi + rd.Next(0, 500)) % 128);
xunHuan++;
}
else
{
//时间前六位表示秒,后10位表示毫秒
int second = DateTime.Now.Second;
int millionSecond = DateTime.Now.Millisecond;
myByte[4 + xunHuan] = (byte)(second * 4 + millionSecond / 128);
xunHuan++;
myByte[4 + xunHuan] = (byte)(millionSecond % 128);
xunHuan++;
}
}
}
//校验逐字节异或的方式
byte bt = myByte[0];
for (int i = 0; i < 108; i++)
{
bt = (byte)(bt ^ myByte[i + 1]);
}
myByte[108] = bt;
return myByte;
}

/**//// <summary>
/// 直流量/遥信帧
/// </summary>
static byte[] ZhiLiuLiang(int num)
{
Random rd = new Random();
byte[] myByte = new byte[17];
//设备号。共1-63个依次发送,其中0号保留
myByte[0] = (byte)(num % shuLiang + 1);
//标志位
myByte[1] = 0xc0;
//直流量数据,四个字节一组。一共两组。
for (int i = 0; i < 8; i++)
{
myByte[2+i] = 0xd;
}
//状态量
myByte[10] = (byte)rd.Next(0, 128);
myByte[11] = (byte)rd.Next(0, 128);
myByte[12] = (byte)rd.Next(0, 128);
myByte[13] = (byte)rd.Next(0, 128);
//时间前六位表示秒,后10位表示毫秒
int second = DateTime.Now.Second;
int millionSecond = DateTime.Now.Millisecond;
myByte[14] = (byte)(second * 4 + millionSecond / 128);
myByte[15] = (byte)(millionSecond % 128);
//校验位
byte bt = myByte[0];
for (int i = 0; i < 16; i++)
{
bt = (byte)(bt ^ myByte[i + 1]);
}
myByte[16] = bt;
return myByte;
}
}
}

/**//*
* 模拟正弦波值。其中最大值为:(30000+加随机值(0-3000)),最小值为:0+随机值(0,3000)
* ,第一帧发送时是将所有的十二个采集的数据都以(坐标为0,0)开始发送
* 其他见word文档
*/
浙公网安备 33010602011771号