C# 多线程网络通信

  

 博客园 :梦工厂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("
输入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# 多线程网络通信

原文地址:https://www.cnblogs.com/dreamfactory/p/3162420.html