博客园 :梦工厂2012
本月由于事情太多,没能有太多的时间去写博客.不过还好在月底抽时间写了这个多线程网络通信的程序 .程序说明:控制端 创建一个写线程threadWrite和一个读线程threadRead ,写线程用于向控制端发送操控指令.读线程用于读取被控制端姿态数据.这里C# 编写了一个模拟被控端ServerConsole .源代码如下,
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Net; 7 using System.Timers; 8 using System.Threading; 9 10 namespace ServerConsole 11 { 12 class Program 13 { 14 //创建写线程 15 private static Thread threadWrite; 16 static int send_num = 0; 17 static NetworkStream streamToClient, streamFromClient; 18 19 static void Main(string[] args) 20 { 21 ushort[] data=new ushort[4]; 22 const int BufferSize = 10; 23 int received_num = 0; 24 byte[] buffer = new byte[BufferSize]; 25 int bytesRead; 26 Console.WriteLine("Server is runing"); 27 28 IPAddress ip = new IPAddress(new byte[]{192,168,0,1}); 29 TcpListener listener = new TcpListener(ip, 8500); 30 31 listener.Start(); 32 Console.WriteLine("Start listening"); 33 while(true) 34 { 35 //为TCP网络服务提供提供客户端连接 36 TcpClient remoteClient = listener.AcceptTcpClient(); //Receive the request of connection 37 // 打印连接到的客户端信息 38 Console.WriteLine("Client Connected!{0} <-- {1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); 39 streamToClient = remoteClient.GetStream(); 40 streamFromClient = remoteClient.GetStream(); 41 42 /*--------------------------------Creat the write thread----------------------------------------*/ 43 threadWrite = new Thread(new ThreadStart(write)); 44 Console.WriteLine("实例化线程"); 45 46 /*-------------------------------------------------------------------------------------------------*/ 47 Handshaking(); //Hand shake ,与上位机进行握手 48 49 while(true) 50 { 51 52 try 53 { 54 bytesRead = streamFromClient.Read(buffer, 0, BufferSize); 55 received_num++; 56 if (bytesRead == 0) throw new Exception("读取到0字节"); 57 58 Console.WriteLine("Reading data,{0}bytes...", bytesRead); 59 60 ushort temp = checksum(buffer, 8); 61 if (temp == ((ushort)buffer[8] + (ushort)(buffer[9] << 8))) 62 { 63 Console.WriteLine("校验正确"); 64 data[0] = (ushort)(buffer[0] + (buffer[1] << 8)); 65 data[1] = (ushort)(buffer[2] + (buffer[3] << 8)); 66 data[2] = (ushort)(buffer[4] + (buffer[5] << 8)); 67 data[3] = (ushort)(buffer[6] + (buffer[7] << 8)); 68 Console.WriteLine("The result is {0},{1},{2},{3},接收{4},发送{5}.", data[0], data[1], data[2], data[3],received_num,send_num); 69 } 70 else 71 Console.WriteLine("校验不正确!"); 72 73 74 } 75 catch (Exception ex) 76 { 77 Console.WriteLine(ex.Message); 78 break; 79 } 80 } //while 81 82 Console.WriteLine("\n输入Q键退出,其他键继续!"); 83 ConsoleKey key; 84 85 key = Console.ReadKey(true).Key; 86 if (key == ConsoleKey.Q) 87 return; 88 else 89 { 90 Console.WriteLine("continute...."); 91 received_num = 0; 92 send_num = 0; 93 } 94 } //whlie 95 } //main 96 97 98 99 private static void write() 100 { 101 byte[] send_byte = new byte[18]; 102 while (true) 103 { 104 for (int i = 0; i < 16;i++ ) 105 { 106 send_byte[i] = (byte)2; 107 } 108 ushort temp = checksum(send_byte, 16); 109 send_byte[16] = (byte)(temp & 0x00ff); //low 110 send_byte[17] = (byte)((temp & 0xff00) >> 8); //high 111 //下面进行数据的发送...... 112 try 113 { 114 streamToClient.Write(send_byte, 0, send_byte.Length); // 发往客户端 115 send_num++; 116 } 117 catch (Exception x) 118 { 119 Console.WriteLine(x.Message); 120 return; 121 } 122 Thread.Sleep(20); 123 } 124 } 125 126 127 /// <summary> 128 /// 与 上位机进行握手 129 /// </summary> 130 private static void Handshaking() 131 { 132 byte[] buffer = new byte[1]; 133 lock (streamFromClient) 134 { 135 int bytesRead = streamFromClient.Read(buffer, 0, 1); 136 Console.WriteLine("Reading data,{0}bytes...", bytesRead); 137 } 138 if (buffer[0] == 0x41) 139 { 140 Console.WriteLine("Received: {0}", Encoding.ASCII.GetString(buffer, 0, buffer.Length)); 141 buffer[0] = 0x42; 142 lock (streamToClient) 143 { 144 streamToClient.Write(buffer, 0, buffer.Length); 145 } 146 Console.WriteLine("sent;{0}", Encoding.ASCII.GetString(buffer, 0, buffer.Length)); 147 148 if(!threadWrite.IsAlive) 149 { 150 threadWrite.Start(); 151 Console.WriteLine("start the write thread "); 152 } 153 154 } 155 } 156 157 158 /// <summary> 159 /// CRC16校验函数 160 /// </summary> 161 /// <param name="array"></param> 162 /// <param name="Len"></param> 163 /// <returns></returns> 164 private static ushort CRC16(char[] array, int Len) 165 { 166 int CRC; 167 UInt16 IX, IY; 168 CRC = 0xffff; //set all 1 169 for (IX = 0; IX < Len; IX++) 170 { 171 172 CRC = CRC ^ (UInt16)(array[IX]); 173 for (IY = 0; IY <= 7; IY++) 174 { 175 if ((CRC & 1) != 0) 176 CRC = (CRC >> 1) ^ 0xA001; 177 else 178 CRC = CRC >> 1; 179 } 180 181 } 182 return (ushort)CRC; 183 } 184 185 //checksum校验 186 private static ushort checksum(byte[] array, int Len) 187 { 188 ushort check_sum = 0, i; 189 //char temp[8]; 190 for (i = 0; i < Len; i += 2) 191 { 192 check_sum += (ushort)((array[i + 1] << 8) + array[i]); 193 } 194 return check_sum; 195 } 196 197 198 199 } 200 }
代码简介:代码写的用点乱,大家将就看吧. 主程序用于接收 控制数据 ,如外我创建一个写线程用于向控制端数据.这里收到的数据我全部写为 (byte)1,发送的数据全部写为(byte)2 ,校验采用累加和校验 .被控端与操控端采用0x41 0x42 进行简单的握手,其实感觉是有点多于了.操控端与被控端没有太大的区别,数据通信部分是相同的,创建连接的代码有点不同.
基本过程:
//实例化通信类
TcpClient client = new TcpClient();
client.Connect(url_conrtol, Convert.ToInt32(portNumber)); // 与服务器连接
streamToServer = client.GetStream();
读写过程 与上面帖的代码相同.
在程序编写过程中,我使用多线程和networkstream 的read,write对流的读写,因为是单机点对点通信并没有发现有什么问题(read 阻塞 ,write 不阻塞 ),read 阻塞不影响发送 . 网上有资料说: Write 和 Read 方法用于简单的单线程同步阻止 I/O。若要使用不同的线程来处理 I/O,则请考虑使用BeginWrite 和 EndWrite 方法,或 BeginRead 和 EndRead 方法进行通信。程序中用用于lock关键字,具体是否起到作用,本人仍在查找资料.
每个程序都是本人花费一定的时间经过多次修改所得,直到程序最优,有些看似简单的问题其实一点也不简单!!博文为本人所写转载请表明出处C# 多线程网络通信