原理是:发送结束后,等待一段时间,判断接收区非空,然后取出数据。
在发送的最后一步: return 接收方法();
return ReadMessage();
接收方法如下:
/// <summary>
/// 读取缓冲区值
/// </summary>
/// <returns></returns>
private byte[] ReadMessage()
{
DateTime startTime = DateTime.Now;//记录开始时间
do
{
if(tcpClient.Available>=1)// 字节
{
#region 计时
//====现在时间======================================
str_发送后记时 = new StringBuilder(String.Format("{0,9}",
DateTime.Now.Second.ToString() + "s"
+ DateTime.Now.Millisecond.ToString() + "ms:")); //固定长度9 右对齐
#endregion
byte[] buffer = new byte[tcpClient.Available];//准备加载
tcpClient.Receive(buffer, buffer .Length, SocketFlags.None);//开始加载
if (Wt_get != null)//委托呼叫ui
{
Wt_get(buffer, str_发送后记时.ToString());// ui显示
}
return buffer;
}
if ((DateTime.Now - startTime).TotalMilliseconds > ReceiveTimeOut)// 超时 1.5s
{
break;// 已经超时
}
} while (true);
return null; // 相当失败
}
最后,延时一下。如 10ms
因为下位机收到命令后,需要一个执行时间。
第2种:
1连接成功后开线程,循环读取数据。
public int connect<T>(T ip, T port)
{
object a = ip;
try
{
Connect((string)a, port.ToString());
Task.Run(new Func<object>(() => { return RXs(); }) ,token );
return 0;
}
catch (Exception ex)
{
source.Cancel();
throw ex;
}
}
public object RXs()
{
while (true)
{
if (tcpClient.Available >= 5)// 字节
{
#region 计时
//====现在时间======================================
ATtime = new StringBuilder(String.Format("{0,9}",
DateTime.Now.Second.ToString() + "s"
+ DateTime.Now.Millisecond.ToString() + "ms:")); //固定长度9 右对齐
#endregion
#region 加载
byte[] buffer = new byte[tcpClient.Available];//准备加载
tcpClient.Receive(buffer, buffer.Length, SocketFlags.None);//开始加载
#endregion
#region 委托
if (Help_ModBus.Wt_get != null)//委托呼叫ui
{
Help_ModBus.Wt_get(buffer, ATtime.ToString());// ui显示
}
#endregion
}
}
}
不要加return,会退出子线程
ui层调用接口:
private void button52_Click(object sender, EventArgs e)
{
try
{
rj45.connect(rj45.ip410s, rj45.port2端口);
//rj45.Connect(rj45.ipDR404, rj45.portDR404);
u_ModBus组件1.help_delta_b3 = b3;
button52.Text = "ok";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
//throw;
}