111,089
社区成员




private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var buffer = new byte[SerialPort.BytesToRead];
SerialPort.Read(buffer, 0, buffer.Length);
DataReceived?.Invoke(this, new ClientDataReceivedEventArgs(this, buffer));
if (tcpClient.Connected && NetworkStream != null)
{
NetworkStream.Write(buffer, 0, buffer.Length);
NetworkStream.Flush();
}
}
[quote=引用 29 楼 baiydn 的回复:] [quote=引用 7 楼 wanghui0380 的回复:] 我很好奇,不管你们用where(true) 也好,还是异步也好,还是所谓的高级xxx园技术Iocp,Nio,还是用的啥XX园的天下第一的supersockect,HighSocket,还是netty,为啥你们你们不是在断线的第一时间收到异常,收到断线事件,收到“已关闭的xxx” 还有人信誓旦旦的说,tcp断线不是第一时间收到断线消息,根据TCP协议,他的2个小时后才能收到消息,那我就纳闷了,这是那些傻叉们设计的tcp协议啊,居然还用了60多年
ar.AcceptSocket.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 1000, 1000), null);
其中KeepAlive方法如下.
public static byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
{
byte[] buffer = new byte[12];
BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
return buffer;
}
我以前也是遇到你所谓的 拔网线不能实时收到消息.. 自从用了这个 完美解决..
[/quote]
我那个回复只是想表达,确实存在2小时后才收到连接断开事件或异常的情况,并不是某些人所谓的什么“信誓旦旦、傻叉...”。
你说的解决办法,可能是重新设置了keepAlive的属性,你是windows平台的。我的项目是linux平台的,java开发的,可能并不支持你所说的解决办法,解决办法有很多种,我只是说了一种简单有效通用的办法。谢谢你的回答,我做的小工具是因为设备只有usb,串口服务器没有USB口。我的串口转tcp是属于Tcp客户端,这个是毋庸置疑的,我之前好像找过相关软件,但是tcp客户端的端口号是随机(应该是递增的)不是固定的 [quote=引用 5 楼 by_封爱 的回复:]
[quote=引用 7 楼 wanghui0380 的回复:] 我很好奇,不管你们用where(true) 也好,还是异步也好,还是所谓的高级xxx园技术Iocp,Nio,还是用的啥XX园的天下第一的supersockect,HighSocket,还是netty,为啥你们你们不是在断线的第一时间收到异常,收到断线事件,收到“已关闭的xxx” 还有人信誓旦旦的说,tcp断线不是第一时间收到断线消息,根据TCP协议,他的2个小时后才能收到消息,那我就纳闷了,这是那些傻叉们设计的tcp协议啊,居然还用了60多年
ar.AcceptSocket.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 1000, 1000), null);
其中KeepAlive方法如下.
public static byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
{
byte[] buffer = new byte[12];
BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
return buffer;
}
我以前也是遇到你所谓的 拔网线不能实时收到消息.. 自从用了这个 完美解决..
我很好奇,不管你们用where(true) 也好,还是异步也好,还是所谓的高级xxx园技术Iocp,Nio,还是用的啥XX园的天下第一的supersockect,HighSocket,还是netty,为啥你们你们不是在断线的第一时间收到异常,收到断线事件,收到“已关闭的xxx” 还有人信誓旦旦的说,tcp断线不是第一时间收到断线消息,根据TCP协议,他的2个小时后才能收到消息,那我就纳闷了,这是那些傻叉们设计的tcp协议啊,居然还用了60多年
你看清楚楼主的图,是设备端通过转换连接服务器,设备通过串口连接转换设备,转换设备从串口接收到数据后,再通过TCP连接服务器,服务器端才是服务端,转换器是客户端。
static list<tcpclient> clients
oncon(tcpclient client)
{
clients.add(client);
}
onclose(tcpclient client);
{
client.remove(client);
}
DataReceived(obj,arg)
{
var data=xxx.read();
clients.foreach(item=>{
item.send(data);
});
}
其实LZ的问题 本来就很简单..是你们想的太复杂了.
那么回到问题上. 收数据的客户端 拔网线了 咋办?
那是客户端的事 在服务端会执行onclose事件. 自动移除.下次不在发送.
至于客户端.拔掉网线的瞬间你会捕获一个异常,至于你重新连接 无非就是一个tcpclient的一个函数而已.
高级点 就整个定时器
所以有的时候 我们在纠结一个问题的时候.并不是因为问题有多难,可能是走进了一个错误的方向.
用错误来验证错误.得到的就是无尽的错误 无尽的讨论....
static void Main(string[] args)
{
using (var tcpClient = new TcpClient("服务器地址写这里", 12345))
using (var networkStream = tcpClient.GetStream())
{
try
{
// 在这个时候,拔掉远程服务器的网线
networkStream.ReadByte();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static void 服务器代码()
{
var tcpListener = new TcpListener(IPAddress.Any, 12345);
tcpListener.Start();
while(true)
{
var socket = tcpListener.AcceptSocket();
Console.WriteLine("客户连接:" + socket.RemoteEndPoint);
Task.Run(() => socket.Receive(new byte[16]));
}
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Socket s = e.AcceptSocket;//和客户端关联的socket
if (s.Connected)
{
try
{
Interlocked.Increment(ref _clientCount);//原子操作加1
SocketAsyncEventArgs asyniar = _objectPool.Pop();
asyniar.UserToken = s;
Log4Debug(String.Format("客户 {0} 连入, 共有 {1} 个连接。", s.RemoteEndPoint.ToString(), _clientCount));
if (!s.ReceiveAsync(asyniar))//投递接收请求
{
ProcessReceive(asyniar);
}
}
catch (SocketException ex)
{
Log4Debug(String.Format("接收客户 {0} 数据出错, 异常信息: {1} 。", s.RemoteEndPoint, ex.ToString()));
//TODO 异常处理
}
//投递下一个接受请求
StartAccept(e);
}
}
}
#endregion
#region 发送数据
/// <summary>
/// 异步的发送数据
/// </summary>
/// <param name="e"></param>
/// <param name="data"></param>
public void Send(SocketAsyncEventArgs e, byte[] data)
{
if (e.SocketError == SocketError.Success)
{
Socket s = e.AcceptSocket;//和客户端关联的socket
if (s.Connected)
{
Array.Copy(data, 0, e.Buffer, 0, data.Length);//设置发送数据
//e.SetBuffer(data, 0, data.Length); //设置发送数据
if (!s.SendAsync(e))//投递发送请求,这个函数有可能同步发送出去,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件
{
// 同步发送时处理发送完成事件
ProcessSend(e);
}
else
{
CloseClientSocket(e);
}
}
}
}
看见没有,但凡不是SocketError.Success一律立刻关闭归还入池(就是reset都不认,因为野数据会让数据包解析混乱,还不如请强制重联呢),强制client重新连接。如果这玩意想上面那位老兄说的,windows2小时以后才知道是不是断线了,额,我表示就是阿里都抗不住,因为我不知道你断线了,我就server就保留你,然后你发不出,重试。我就是给个long.MaxValue的池都不够用的,因为你们2小时1w连接都不知道重试多少次了。
对于tcpclient其实也是一样,send有异常,read异常,BeginRead,全都会有异常。楼主,为什么不考虑RJ45转232或者485,然后在232或者485转串口呢?这样就可以不用考虑使用PC机,只是增加了两根线而已