您的位置:首页 > 理论基础 > 计算机网络

C# 多线程网络通信

2013-06-29 16:29 183 查看
  

 博客园 :梦工厂2012   

  本月由于事情太多,没能有太多的时间去写博客.不过还好在月底抽时间写了这个多线程网络通信的程序 .程序说明:控制端 创建一个写线程threadWrite和一个读线程threadRead ,写线程用于向控制端发送操控指令.读线程用于读取被控制端姿态数据.这里C# 编写了一个模拟被控端ServerConsole .源代码如下,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Timers;
using System.Threading;

namespace ServerConsole
{
class Program
{
//创建写线程
private static Thread threadWrite;
static int send_num = 0;
static NetworkStream streamToClient, streamFromClient;

static void Main(string[] args)
{
ushort[] data=new ushort[4];
const int BufferSize = 10;
int received_num = 0;
byte[] buffer = new byte[BufferSize];
int bytesRead;
Console.WriteLine("Server is runing");

IPAddress ip = new IPAddress(new byte[]{192,168,0,1});
TcpListener listener = new TcpListener(ip, 8500);

listener.Start();
Console.WriteLine("Start listening");
while(true)
{
//为TCP网络服务提供提供客户端连接
TcpClient remoteClient = listener.AcceptTcpClient();    //Receive the request of connection
// 打印连接到的客户端信息
Console.WriteLine("Client Connected!{0} <-- {1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
streamToClient = remoteClient.GetStream();
streamFromClient = remoteClient.GetStream();

/*--------------------------------Creat the write thread----------------------------------------*/
threadWrite = new Thread(new ThreadStart(write));
Console.WriteLine("实例化线程");

/*-------------------------------------------------------------------------------------------------*/
Handshaking();  //Hand shake  ,与上位机进行握手

while(true)
{

try
{
bytesRead = streamFromClient.Read(buffer, 0, BufferSize);
received_num++;
if (bytesRead == 0) throw new Exception("读取到0字节");

Console.WriteLine("Reading data,{0}bytes...", bytesRead);

ushort temp = checksum(buffer, 8);
if (temp == ((ushort)buffer[8] + (ushort)(buffer[9] << 8)))
{
Console.WriteLine("校验正确");
data[0] = (ushort)(buffer[0] + (buffer[1] << 8));
data[1] = (ushort)(buffer[2] + (buffer[3] << 8));
data[2] = (ushort)(buffer[4] + (buffer[5] << 8));
data[3] = (ushort)(buffer[6] + (buffer[7] << 8));
Console.WriteLine("The result is {0},{1},{2},{3},接收{4},发送{5}.", data[0], data[1], data[2], data[3],received_num,send_num);
}
else
Console.WriteLine("校验不正确!");

}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
break;
}
} //while

Console.WriteLine("\n输入Q键退出,其他键继续!");
ConsoleKey key;

key = Console.ReadKey(true).Key;
if (key == ConsoleKey.Q)
return;
else
{
Console.WriteLine("continute....");
received_num = 0;
send_num = 0;
}
}   //whlie
}  //main

private static void write()
{
byte[] send_byte = new byte[18];
while (true)
{
for (int i = 0; i < 16;i++ )
{
send_byte[i] = (byte)2;
}
ushort temp = checksum(send_byte, 16);
send_byte[16] = (byte)(temp & 0x00ff);                           //low
send_byte[17] = (byte)((temp & 0xff00) >> 8);           //high
//下面进行数据的发送......
try
{
streamToClient.Write(send_byte, 0, send_byte.Length);      // 发往客户端
send_num++;
}
catch (Exception x)
{
Console.WriteLine(x.Message);
return;
}
Thread.Sleep(20);
}
}

/// <summary>
/// 与 上位机进行握手
/// </summary>
private static void Handshaking()
{
byte[] buffer = new byte[1];
lock (streamFromClient)
{
int bytesRead = streamFromClient.Read(buffer, 0, 1);
Console.WriteLine("Reading data,{0}bytes...", bytesRead);
}
if (buffer[0] == 0x41)
{
Console.WriteLine("Received: {0}", Encoding.ASCII.GetString(buffer, 0, buffer.Length));
buffer[0] = 0x42;
lock (streamToClient)
{
streamToClient.Write(buffer, 0, buffer.Length);
}
Console.WriteLine("sent;{0}", Encoding.ASCII.GetString(buffer, 0, buffer.Length));

if(!threadWrite.IsAlive)
{
threadWrite.Start();
Console.WriteLine("start the write thread ");
}

}
}

/// <summary>
/// CRC16校验函数
/// </summary>
/// <param name="array"></param>
/// <param name="Len"></param>
/// <returns></returns>
private static ushort CRC16(char[] array, int Len)
{
int CRC;
UInt16 IX, IY;
CRC = 0xffff;   //set all 1
for (IX = 0; IX < Len; IX++)
{

CRC = CRC ^ (UInt16)(array[IX]);
for (IY = 0; IY <= 7; IY++)
{
if ((CRC & 1) != 0)
CRC = (CRC >> 1) ^ 0xA001;
else
CRC = CRC >> 1;
}

}
return (ushort)CRC;
}

//checksum校验
private static ushort checksum(byte[] array, int Len)
{
ushort check_sum = 0, i;
//char temp[8];
for (i = 0; i < Len; i += 2)
{
check_sum += (ushort)((array[i + 1] << 8) + array[i]);
}
return check_sum;
}

}
}


代码简介:代码写的用点乱,大家将就看吧. 主程序用于接收 控制数据 ,如外我创建一个写线程用于向控制端数据.这里收到的数据我全部写为 (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 阻塞不影响发送 . 网上有资料说: WriteRead 方法用于简单的单线程同步阻止 I/O。若要使用不同的线程来处理 I/O,则请考虑使用BeginWriteEndWrite 方法,或 BeginReadEndRead 方法进行通信。程序中用用于lock关键字,具体是否起到作用,本人仍在查找资料.



每个程序都是本人花费一定的时间经过多次修改所得,直到程序最优,有些看似简单的问题其实一点也不简单!!博文为本人所写转载请表明出处C# 多线程网络通信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: