2015-04-08 update 1 change some code in TCP Connector to implement async method

This commit is contained in:
parallelbgls@outlook.com
2015-04-08 15:41:20 +08:00
parent 3f4fe27a5e
commit a9bcd06b2b
12 changed files with 158 additions and 122 deletions

View File

@@ -15,6 +15,11 @@ namespace ModBus.Net
/// <returns></returns>
public abstract bool Connect();
/// <summary>
/// 连接PLC异步
/// </summary>
/// /// <returns></returns>
public abstract Task<bool> ConnectAsync();
/// <summary>
/// 断开PLC
/// </summary>
/// <returns></returns>
@@ -26,10 +31,22 @@ namespace ModBus.Net
/// <returns></returns>
public abstract bool SendMsgWithoutReturn(byte[] message);
/// <summary>
/// 无返回发送数据,异步
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public abstract Task<bool> SendMsgWithoutReturnAsync(byte[] message);
/// <summary>
/// 带返回发送数据
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public abstract byte[] SendMsg(byte[] message);
/// <summary>
/// 带返回发送数据,异步
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public abstract Task<byte[]> SendMsgAsync(byte[] message);
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
namespace ModBus.Net
{

View File

@@ -52,6 +52,11 @@ namespace ModBus.Net
return false;
}
public override Task<bool> ConnectAsync()
{
return Task.FromResult(Connect());
}
public override bool Disconnect()
{
if (serialPort1 != null)
@@ -77,6 +82,11 @@ namespace ModBus.Net
}
public override Task<bool> SendMsgWithoutReturnAsync(byte[] message)
{
return Task.FromResult(SendMsgWithoutReturn(message));
}
public override byte[] SendMsg(byte[] sendbytes)
{
try
@@ -95,6 +105,11 @@ namespace ModBus.Net
}
}
public override Task<byte[]> SendMsgAsync(byte[] message)
{
return Task.FromResult(SendMsg(message));
}
public override bool SendMsgWithoutReturn(byte[] sendbytes)
{
try

View File

@@ -30,6 +30,12 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>key.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -42,6 +48,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AddressTranslator.cs" />
<Compile Include="AsyncHelper.cs" />
<Compile Include="BaseProtocal.cs" />
<Compile Include="BaseUtility.cs" />
<Compile Include="ComConnector.cs" />
@@ -82,6 +89,9 @@
<LastGenOutput>ConfigurationManager.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="key.pfx" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
/// <summary>

View File

@@ -1,4 +1,5 @@
using System.Reflection;
using System.Threading.Tasks;
namespace ModBus.Net
{

View File

@@ -34,6 +34,16 @@ namespace ModBus.Net
_maxPdu = 0x03c0;
break;
}
case "300":
case "400":
{
_taspSrc = 0x4b54;
_tsapDst = 0x0302;
_maxCalling = 0x0001;
_maxCalled = 0x0001;
_maxPdu = 0x00f0;
break;
}
}
_connectionString = splitStrings[0];
}

View File

@@ -1,6 +1,9 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
namespace ModBus.Net
{
@@ -23,68 +26,73 @@ namespace ModBus.Net
/// </summary>
public class TcpConnector : BaseConnector, IDisposable
{
public delegate void ErrorShutdownEventHandler(object sender, EventArgs e);
public delegate void ReceiveMessageHandler(object sender, SocketMessageEventArgs e);
private readonly string _host;
private readonly bool b_AsyncReceive = true;
private readonly string host;
private int _sendCount;
private int _receiveCount;
private int _errorCount;
private NetworkStream _stream;
// 2MB 的接收缓冲区,目的是一次接收完服务器发回的消息
private readonly byte[] m_receiveBuffer = new byte[1024];
private readonly int port;
public int m_errorCount = 0;
public int m_receiveCount = 0;
public int m_sendCount = 0;
private TcpClient m_socketClient;
private readonly byte[] _receiveBuffer = new byte[1024];
private readonly int _port;
private TcpClient _socketClient;
public TcpConnector(string ipaddress, int port, bool isAsync)
public int TimeoutTime { get; set; }
public TcpConnector(string ipaddress, int port, int timeoutTime)
{
host = ipaddress;
this.port = port;
b_AsyncReceive = isAsync;
_host = ipaddress;
_port = port;
//TimeoutTime = timeoutTime;
}
public override bool IsConnected
{
get { return m_socketClient != null && m_socketClient.Connected; }
get { return _socketClient != null && _socketClient.Connected; }
}
public void Dispose()
{
if (m_socketClient != null)
if (_socketClient != null)
{
CloseClientSocket();
m_socketClient.Client.Dispose();
}
}
public event ReceiveMessageHandler MessageReceive;
public event ErrorShutdownEventHandler SocketErrorShutdown;
private void ReceiveMessage(byte[] message)
{
if (MessageReceive != null)
{
MessageReceive(this, new SocketMessageEventArgs(message));
_socketClient.Client.Dispose();
}
}
public override bool Connect()
{
if (m_socketClient != null)
return AsyncHelper.RunSync(ConnectAsync);
}
public override async Task<bool> ConnectAsync()
{
if (_socketClient != null)
{
Disconnect();
}
lock (this)
{
try
{
m_socketClient = new TcpClient(host, port);
m_socketClient.ReceiveTimeout = 10*1000;
if (m_socketClient.Connected)
_socketClient = new TcpClient
{
SendTimeout = TimeoutTime,
ReceiveTimeout = TimeoutTime
};
try
{
await _socketClient.ConnectAsync(_host, _port);
}
catch (Exception e)
{
AddInfo("client connected exception: " + e.Message);
}
if (_socketClient.Connected)
{
_stream = _socketClient.GetStream();
AddInfo("client connected.");
return true;
}
@@ -97,20 +105,17 @@ namespace ModBus.Net
return false;
}
}
}
public override bool Disconnect()
{
lock (this)
{
if (m_socketClient == null)
if (_socketClient == null)
{
return true;
}
try
{
m_socketClient.Close();
_socketClient.Close();
AddInfo("client disconnected successfully.");
return true;
}
@@ -121,8 +126,7 @@ namespace ModBus.Net
}
finally
{
m_socketClient = null;
}
_socketClient = null;
}
}
@@ -131,18 +135,28 @@ namespace ModBus.Net
Console.WriteLine(message);
}
public override bool SendMsgWithoutReturn(byte[] message)
{
return AsyncHelper.RunSync(() => SendMsgWithoutReturnAsync(message));
}
/// <summary>
/// 发送数据,不需要返回任何值
/// </summary>
/// <param name="message">发送的信息</param>
/// <returns>是否发送成功</returns>
public override bool SendMsgWithoutReturn(byte[] message)
public override async Task<bool> SendMsgWithoutReturnAsync(byte[] message)
{
byte[] datagram = message;
try
{
m_socketClient.Client.Send(datagram);
if (!IsConnected)
{
await ConnectAsync();
}
await _stream.WriteAsync(datagram, 0, datagram.Length);
RefreshSendCount();
//this.AddInfo("send text len = " + datagramText.Length.ToString());
@@ -156,12 +170,17 @@ namespace ModBus.Net
}
}
public override byte[] SendMsg(byte[] message)
{
return AsyncHelper.RunSync(() => SendMsgAsync(message));
}
/// <summary>
/// 发送数据,需要返回
/// </summary>
/// <param name="message">发送的数据</param>
/// <returns>是否发送成功</returns>
public override byte[] SendMsg(byte[] message)
public override async Task<byte[]> SendMsgAsync(byte[] message)
{
byte[] datagram = message;
@@ -169,14 +188,16 @@ namespace ModBus.Net
{
if (!IsConnected)
{
Connect();
await ConnectAsync();
}
m_socketClient.Client.Send(datagram);
var stream = _socketClient.GetStream();
await stream.WriteAsync(datagram, 0, datagram.Length);
RefreshSendCount();
//this.AddInfo("send text len = " + datagramText.Length.ToString());
return Receive();
return await ReceiveAsync(stream);
}
catch (Exception err)
{
@@ -186,19 +207,12 @@ namespace ModBus.Net
}
}
public byte[] Receive()
protected async Task<byte[]> ReceiveAsync(NetworkStream stream)
{
try
{
int len = await stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length);
// 异步接收回答
if (b_AsyncReceive)
{
m_socketClient.Client.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None,
EndReceiveDatagram, this);
return null;
}
// 同步接收回答
int len = m_socketClient.Client.Receive(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None);
if (len > 0)
{
return CheckReplyDatagram(len);
@@ -220,10 +234,9 @@ namespace ModBus.Net
private byte[] CheckReplyDatagram(int len)
{
var replyMessage = new byte[len];
Array.Copy(m_receiveBuffer, replyMessage, len);
Array.Copy(_receiveBuffer, replyMessage, len);
//this.AddInfo("reply: " + replyMesage);
ReceiveMessage(replyMessage);
RefreshReceiveCount();
if (len <= 0)
@@ -236,63 +249,30 @@ namespace ModBus.Net
private void RefreshSendCount()
{
m_sendCount++;
_sendCount++;
}
private void RefreshReceiveCount()
{
m_receiveCount++;
_receiveCount++;
}
private void RefreshErrorCount()
{
m_errorCount++;
_errorCount++;
}
private void CloseClientSocket()
{
try
{
m_socketClient.Client.Shutdown(SocketShutdown.Both);
m_socketClient.Client.Close();
if (!IsConnected)
{
if (SocketErrorShutdown != null)
{
Thread.Sleep(1000);
SocketErrorShutdown(this, new EventArgs());
AddInfo("socket error disconnected!");
}
}
_stream.Close();
_socketClient.Client.Shutdown(SocketShutdown.Both);
_socketClient.Client.Close();
}
catch (Exception ex)
{
//this.AddInfo("client close exception: " + ex.Message);
}
}
/// <summary>
/// 异步接收消息返回函数
/// </summary>
/// <param name="iar">异步参数</param>
private void EndReceiveDatagram(IAsyncResult iar)
{
try
{
int readBytesLength = m_socketClient.Client.EndReceive(iar);
if (readBytesLength == 0)
{
CloseClientSocket();
}
else // 正常数据包
{
CheckReplyDatagram(readBytesLength);
}
}
catch (Exception err)
{
AddInfo("receive exception: " + err.Message);
CloseClientSocket();
AddInfo("client close exception: " + ex.Message);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace ModBus.Net
{
@@ -17,7 +18,7 @@ namespace ModBus.Net
protected TcpProtocalLinker(string ip, int port)
{
_baseConnector = new TcpConnector(ip, port, false);
_baseConnector = new TcpConnector(ip, port, 10000);
}
}
}

View File

@@ -25,7 +25,7 @@ namespace ModBus.Net
{"System.Double", 8}
};
protected static bool _littleEndian = false;
protected static bool _littleEndian = true;
protected ValueHelper()
{
@@ -41,7 +41,7 @@ namespace ModBus.Net
{
_littleEndian = value;
//这里需要重点说明,因为.net默认是小端构造法所以目标协议是大端的话反而需要调用小端构造协议把小端反转为大端。
_Instance = LittleEndian ? new ValueHelper() : new LittleEndianValueHelper();
_Instance = LittleEndian ? new LittleEndianValueHelper() : new ValueHelper();
}
}
@@ -58,7 +58,7 @@ namespace ModBus.Net
{
if (_Instance == null)
{
_Instance = LittleEndian ? new ValueHelper() : new LittleEndianValueHelper();
_Instance = LittleEndian ? new LittleEndianValueHelper() : new ValueHelper();
}
return _Instance;
}
@@ -285,7 +285,7 @@ namespace ModBus.Net
byte temp = data[pos];
for (int i = 0; i < 8; i++)
{
t[7 - i] = temp%2 > 0;
t[i] = temp % 2 > 0;
temp /= 2;
}
pos += 1;
@@ -709,7 +709,7 @@ namespace ModBus.Net
byte temp = data[pos];
for (int i = 0; i < 8; i++)
{
t[i] = temp%2 > 0;
t[7 - i] = temp % 2 > 0;
temp /= 2;
}
pos += 1;

Binary file not shown.