现在需要进一步学习多线程的知识,11年年初的时候写的程序,测试可以使用,但是对于多线程的机制还是不十分清楚,所以再拿出来看看。
1.读取Udp协议数据服务器端程序(图2):
(1) (2)
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 using System.Runtime.InteropServices; 9 using System.Net; 10 using System.Net.Sockets; 11 using System.Threading; 12 13 namespace ServerUdp 14 { 15 public partial class Serverfrm : Form 16 { 17 UdpClient udpReceive; 18 private Thread myThread; 19 private delegate void SetlistBoxCallBack(string str);//委托, 20 private SetlistBoxCallBack setlistbox; 21 22 public Serverfrm() 23 { 24 InitializeComponent(); 25 } 26 27 private void Serverfrm_Load(object sender, EventArgs e) 28 { 29 setlistbox = new SetlistBoxCallBack(SetListBox); 30 } 31 private void ReceiveMessage() 32 { 33 // mDB_means.Open(); 34 byte[] ReceiveBytes = null; 35 IPEndPoint remoteIpEndIPoint = new IPEndPoint(IPAddress.Any, 29527); 36 udpReceive = new UdpClient(remoteIpEndIPoint); 37 IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); 38 while (true) 39 { 40 try 41 { 42 ReceiveBytes = udpReceive.Receive(ref iep); 43 } 44 catch (Exception ex) 45 { 46 MessageBox.Show(ex.ToString()); 47 return; 48 } 49 finally 50 { 51 } 52 int pPoint = 0; 53 string message = "来自" + iep.ToString() + "的消息"; 54 Head phead = new Head(); 55 System.Type ptype = phead.GetType(); 56 phead = (Head)BytesToStruct(ReceiveBytes, ptype, 0); 57 pPoint +=Marshal.SizeOf(phead); 58 59 StationID apid = new StationID(); 60 System.Type ptype1 = apid.GetType(); 61 apid = (StationID)BytesToStruct(ReceiveBytes, ptype1, pPoint); 62 pPoint +=Marshal.SizeOf(apid ); 63 64 listBox1.Invoke(setlistbox, message); 65 66 int p=0; 67 foreach (byte flg in phead.flag) 68 { 69 if (flg != '\0') 70 p++; 71 } 72 byte[] tempbyte = new byte[p]; 73 for (int i = 0; i < p; i++) 74 tempbyte[i] = phead.flag[i]; 75 76 string export =Encoding.UTF8.GetString (tempbyte ) + " " + phead.len.ToString() + " " + phead.type.ToString() + " " + phead.cmd.ToString() + " " + phead.rc.ToString(); 77 listBox1.Invoke(setlistbox, export); 78 listBox1.Invoke(setlistbox, Encoding.UTF8.GetString(apid.serial)); 79 80 if (phead.cmd == 2) 81 { 82 PacketData pPacketData = new PacketData(); 83 int ind=Convert.ToInt16 ((phead.len -pPoint)/Marshal.SizeOf (pPacketData )) ; 84 System.Type ptype2 = pPacketData.GetType(); 85 86 for (int i = 1; i <= ind; i++) 87 { 88 pPacketData = (PacketData)BytesToStruct(ReceiveBytes, ptype2, pPoint); 89 pPoint += Marshal.SizeOf(pPacketData); 90 string addrstr1 = ""; 91 foreach (byte tele in pPacketData.Kid ) 92 { 93 addrstr1 += Convert.ToString(tele); 94 } 95 listBox1.Invoke(setlistbox, addrstr1 + " " + pPacketData.rssi.ToString() + " " + pPacketData.time.ToString()); 96 // listBox1.Invoke(setlistbox, pPacketData.Kid + " " + pPacketData.rssi.ToString() + " " + pPacketData.time.ToString()); 97 98 } 99 } 100 else if (phead.cmd == 1) 101 { 102 WifiData pWifiData = new WifiData(); 103 int ind = Convert.ToInt16((phead.len - pPoint) / Marshal.SizeOf(pWifiData)); 104 System.Type ptype3 = pWifiData.GetType(); 105 for (int i = 1; i <= ind; i++) 106 { 107 pWifiData = (WifiData)BytesToStruct(ReceiveBytes, ptype3, pPoint); 108 pPoint += Marshal.SizeOf(pWifiData); 109 string addrstr = ""; 110 foreach (byte bele in pWifiData.addr) 111 { 112 addrstr +=bele.ToString("X")+":" ; 113 } 114 listBox1.Invoke(setlistbox, addrstr + " " + pWifiData.rssi.ToString() + " " + pWifiData.rate.ToString() + " " + pWifiData.time.ToString()); 115 try 116 { 117 118 // string SQL = "insert into 接收AP信息 values('" + Encoding.UTF8.GetString(pPacketData.Kid) + "','" + pPacketData.rssi + "','" + pPacketData.time + "','" + Encoding.UTF8.GetString(apid.serial) + "')"; 119 // int ii = mDB_means.Operate(SQL); 120 121 } 122 catch (Exception ex) 123 { 124 125 } 126 finally 127 { 128 //continue; 129 } 130 } 131 } 132 133 //AddKaoQ(list1, phead);//将接收的数据转换成需要的考勤信息数组和位置解算数组 134 //Store(list1); 135 } 136 137 } 138 private void SetListBox(string str) 139 { 140 listBox1.Items.Add(str); 141 listBox1.SelectedIndex = listBox1.Items.Count - 1; 142 listBox1.ClearSelected(); 143 } 144 private void btnStop_Click(object sender, EventArgs e) 145 { 146 147 btnStart.Enabled = true; 148 udpReceive.Close (); 149 myThread.Abort(); 150 } 151 152 private void Serverfrm_FormClosed(object sender, FormClosedEventArgs e) 153 { 154 udpReceive.Close(); 155 myThread.Abort(); 156 } 157 public object BytesToStruct(byte[] bytes, Type type, int p) 158 { 159 //得到结构的大小 160 int size = Marshal.SizeOf(type); 161 //Log(size.ToString(), 1); 162 //byte数组长度小于结构的大小 163 if (size > bytes.Length) 164 { 165 //返回空 166 return null; 167 } 168 //分配结构大小的内存空间 169 IntPtr structPtr = Marshal.AllocHGlobal(size); 170 //将byte数组拷到分配好的内存空间 171 Marshal.Copy(bytes, p, structPtr, size); 172 //将内存空间转换为目标结构 173 object obj = Marshal.PtrToStructure(structPtr, type); 174 //释放内存空间 175 Marshal.FreeHGlobal(structPtr); 176 //返回结构 177 return obj; 178 } 179 180 private void btnStart_Click(object sender, EventArgs e) 181 { 182 btnStart.Enabled = false; 183 184 myThread = new Thread(new ThreadStart(ReceiveMessage)); 185 myThread.Start(); 186 187 } 188 189 190 191 192 } 193 }
数据结构如下:
数据包数据结构
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 using System.Net; 9 using System.Net.Sockets; 10 using System.Runtime.InteropServices; 11 //System.Runtime.InteropServices 命名空间提供各种各样支持 COM interop 及平台调用服务的成员 12 //此命名空间提供了多种类别的功能,如下表所示。 13 //属性可控制封送行为,例如如何安排结构或表示字符串。 14 //其中最重要的属性有 DllImportAttribute(可以用来定义用于访问非托管 API 的平台调用方法)和 15 //MarshalAsAttribute(可以用来指定如何在托管内存与非托管内存之间封送数据)。 16 namespace ServerUdp 17 { 18 struct Head 19 { 20 //head头长为12 字节 21 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 22 public byte[] flag; //AQD,用来标志数据,默认值为“AQD”,4个字节 23 public uint len; //all transimit len,用来表示整个数据头和数据部分的总,长度4个字节 24 public byte type; //packet type, 0: request 1: respond 2:report,数据类型,1个字节 25 //packet command1:代表 wifi 手机的数据2:代表 人员定位卡的数据 26 public sbyte cmd; //1个字节 27 28 //return code, 0 correct, other error 29 //用于说明本次数据是否有效,主要是用于被动模式下,当服务器请求数据,而AP应答时,说明数据是否请求成功,或者表示错误的代码, 30 //主动模式下没有意义。此值为两个字节长,默认值为0。 31 public UInt16 rc;//2 个字节 32 33 34 } 35 public struct PacketData//人员定位卡数据 36 { 37 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 38 public byte[] Kid;//人员定位卡号码,3个字节 39 public byte rssi;//信号强度1字节 40 public uint time;//获取信号的时间,4个字节,其中时间的表示为从2010-1-1-0:00到取得信号时的间隔秒数 41 42 } 43 struct StationID 44 { 45 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 46 public byte[] serial; 47 } 48 public struct WifiData//Wifi手机数据 49 { 50 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 51 public Byte[] addr;//WIFI 模块MAC,6字节 52 public sbyte rssi;//信号强度,1字节 53 public byte rate;//模块的通讯速度,1字节 54 public uint time;//获取信号的时间,4字节,其中时间的表示为从2010-1-1-0:00到取得信号时的间隔秒数 55 56 } 57 }
2.发送数据测试程序(图1):
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 using System.Collections; 9 using System.Net; 10 using System.Net.Sockets; 11 using System.Runtime.InteropServices; 12 13 namespace ApUdp 14 { 15 public partial class Apfrm : Form 16 { 17 UdpClient udpSend; 18 public Apfrm() 19 { 20 InitializeComponent(); 21 } 22 23 private void button1_Click(object sender, EventArgs e) 24 { 25 //DateTime pdatetime = new DateTime(); 26 //DateTime PdateTime = new DateTime(2010, 1, 1); 27 //pdatetime = DateTime.Now; 28 //TimeSpan aa = pdatetime - PdateTime; 29 //MessageBox.Show(aa.TotalDays.ToString() + " " + aa.TotalHours.ToString() + " " + Convert .ToString (aa.TotalDays *24) + " " + aa.TotalSeconds.ToString()); 30 31 timer1.Enabled = !timer1.Enabled; 32 33 } 34 35 private void timer1_Tick(object sender, EventArgs e) 36 { 37 //基站编号 38 StationID apid = new StationID(); 39 //apid.serial =new byte[]{1,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0}; 40 apid.serial = Encoding.UTF8.GetBytes(new char[] { 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'a', 'p', '0', '1' }); 41 42 DateTime pNowTime = new DateTime(); 43 DateTime pDateTime = new DateTime(2010, 1, 1); 44 pNowTime = DateTime.Now; 45 TimeSpan pTimeSpan = pNowTime - pDateTime;//时间间隔 46 47 //定位卡数据2份 48 PacketData pPacketData1 = new PacketData(); 49 pPacketData1.Kid = Encoding.UTF8.GetBytes("k01"); 50 pPacketData1.rssi = 1; 51 pPacketData1.time =Convert .ToUInt32 ( pTimeSpan.TotalSeconds); 52 53 PacketData pPacketData2 = new PacketData(); 54 pPacketData2.Kid = Encoding.UTF8.GetBytes("k02"); 55 pPacketData2.rssi = 1; 56 pPacketData2.time =Convert.ToUInt32 ( pTimeSpan.TotalSeconds); 57 58 PacketData pPacketData3 = new PacketData(); 59 pPacketData3.Kid = Encoding.UTF8.GetBytes("k03"); 60 pPacketData3.rssi = 2; 61 pPacketData3.time = Convert.ToUInt32(pTimeSpan.TotalSeconds); 62 63 //头数据 64 Head headap1 = new Head(); 65 //headap1.flag = new byte[] { (byte)'A', (byte)'P', 0, 1 }; 66 headap1.flag = Encoding.UTF8.GetBytes(new char[] { 'A', 'D', 'Q', ' ' }); 67 headap1.len = Convert.ToUInt32( Marshal.SizeOf(headap1)+Marshal.SizeOf (apid )+2*Marshal.SizeOf (pPacketData1)) ; 68 headap1.type = 2;//标识主动上报 69 headap1.cmd = 2;//表示Wifi手机 70 headap1.rc = 0;//默认为0 71 72 byte[] aa = StructToBytes(headap1);//转换成字节数组 73 byte[] bb = StructToBytes(apid );//转换成字节数组 74 byte[] cc = StructToBytes(pPacketData1);//转换成字节数组 75 byte[] dd = StructToBytes(pPacketData2);//转换成字节数组 76 77 byte[] SendBytes =new byte[headap1.len ];//转换成字节数组 78 aa.CopyTo(SendBytes, 0); 79 bb.CopyTo(SendBytes, aa.Length ); 80 cc.CopyTo(SendBytes, aa.Length + bb.Length ); 81 dd.CopyTo(SendBytes, aa.Length +cc.Length + bb.Length ); 82 83 System.Type ptype = headap1.GetType(); 84 Head TestBytesbb = (Head)BytesToStruct(SendBytes, ptype,0); 85 System.Type ptype1 =apid.GetType(); 86 StationID TestBytes = (StationID)BytesToStruct(SendBytes, ptype1, Marshal.SizeOf (TestBytesbb)); 87 #region 利用Arraylist尝试 88 //ArrayList parraylist = new ArrayList(); 89 //parraylist.Add(headap1); 90 //parraylist.Add(apid); 91 //parraylist.Add(pPacketData1); 92 //parraylist.Add(pPacketData2); 93 94 //byte[] aa = StructToBytes(headap1);//转换成字节数组 95 //System.Type ptype1 = headap1.GetType(); 96 //Head bb = (Head)BytesToStruct(aa, ptype1); 97 98 //byte[] SendBytes = StructToBytes(parraylist );//转换成字节数组 99 //System.Type ptype = parraylist.GetType(); 100 //Head TestBytes = (Head)BytesToStruct(SendBytes, ptype); 101 102 //MessageBox.Show(headap1.len .ToString ()+" "+SendBytes.Length .ToString ()); 103 #endregion 104 try 105 { 106 udpSend = new UdpClient(); 107 IPAddress remoteIPAddress = IPAddress.Parse("127.0.0.1"); 108 IPEndPoint remoteIPEndPoint = new IPEndPoint(remoteIPAddress, 29527); 109 udpSend.Send(SendBytes, SendBytes.Length, remoteIPEndPoint); 110 111 listBox1.Items.Add(Encoding.UTF8.GetString(TestBytesbb.flag) + " " + TestBytesbb.len.ToString() + " " + TestBytesbb.type.ToString() + " " + TestBytesbb.cmd.ToString() + " " + TestBytesbb.rc.ToString()); 112 listBox1.Items.Add(Encoding.UTF8 .GetString(TestBytes.serial)); 113 } 114 catch (Exception ex) 115 { 116 MessageBox.Show(ex.ToString()); 117 return; 118 } 119 finally 120 { 121 } 122 } 123 /// <summary> 124 /// 将结构转换为字节数组 125 /// </summary> 126 /// <param name="obj">结构对象</param> 127 /// <returns>字节数组</returns> 128 public byte[] StructToBytes(object obj) 129 { 130 //得到结构体的大小 131 int size = Marshal.SizeOf(obj); 132 //创建byte数组 133 byte[] bytes = new byte[size]; 134 //分配结构体大小的内存空间 135 IntPtr structPtr = Marshal.AllocHGlobal(size); 136 //将结构体拷到分配好的内存空间 137 Marshal.StructureToPtr(obj, structPtr, false); 138 //从内存空间拷到byte数组 139 Marshal.Copy(structPtr, bytes, 0, size); 140 //释放内存空间 141 Marshal.FreeHGlobal(structPtr); 142 //返回byte数组 143 return bytes; 144 } 145 /// <summary> 146 /// byte数组转结构 147 /// </summary> 148 /// <param name="bytes">byte数组</param> 149 /// <param name="type">结构类型</param> 150 // <returns>转换后的结构</returns> 151 public object BytesToStruct(byte[] bytes,Type type ,int p) 152 { 153 //得到结构的大小 154 int size = Marshal.SizeOf(type); 155 //Log(size.ToString(), 1); 156 //byte数组长度小于结构的大小 157 if (size > bytes.Length) 158 { 159 //返回空 160 return null; 161 } 162 //分配结构大小的内存空间 163 IntPtr structPtr = Marshal.AllocHGlobal(size); 164 //将byte数组拷到分配好的内存空间 165 Marshal.Copy (bytes, p, structPtr, size); 166 //将内存空间转换为目标结构 167 object obj = Marshal.PtrToStructure(structPtr, type); 168 //释放内存空间 169 Marshal.FreeHGlobal(structPtr); 170 //返回结构 171 return obj; 172 } 173 174 } 175 }