求助 tcpclient 报“由于目标计算机积极拒绝,无法连接”

yang1216 2014-12-29 10:37:39
我的client端每秒发送一个指令给server端,然后接收server端的数据。程序正常执行300个循环后,报错:
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: 由于目标计算机积极拒绝,无法连接。

下面是我的代码:

public void Poll()
{

foreach (var station in stations)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPollCallback), COMMStates[station.Id]);
}

if (WaitHandle.WaitAll(COMMStates.Select(p => p.Value.Completed).ToArray(), millsecondsTimeout, false))
{
}
else
{
Console.WriteLine("timeout");
foreach (var cs in COMMStates)
{
if (cs.Value != null)
{
cs.Value.Abort();
}
}
}
}
public void ThreadPollCallback(object state)
{
var cs = state as COMMState;
if (cs == null) return;
var station = cs.Station;


using (TcpClient tc = new TcpClient(station.IP, 3100)) //在这里报错
{
try
{
Console.WriteLine("comm thread start");
if (cs.Aborted)
{
Console.WriteLine("comm thread abort");
try
{
tc.GetStream().Close();
}
catch
{
}
try { tc.Close(); }
catch { }
}
else
{
COMMIpMaster master = COMMIpMaster.CreateIp(tc);

var length = master.ReadWaveLength();//这里就是一个write,一个read
if (length % 24 != 0)
{
throw new Exception("长度不正确");
}
ushort[] res = master.ReadWaveData((ushort)length);//这里就是一个write,一个read
lock (lockObj)
{
Data[station.Id] = new List<ushort>(res);
stationErrNum[station.Id] = 0;
Exceptions[station.Id] = null;
}
}
}
catch (Exception e)
{
Console.WriteLine("comm thread error");
lock (lockObj)
{
Exceptions[station.Id] = e;
stationErrNum[station.Id]++;
if (stationErrNum[station.Id] > 3)
{
Data[station.Id] = new List<ushort>(12); ;
}
}
}
finally
{
cs.Completed.Set();
}
}
}
public class COMMState
{
public Station Station;
public volatile Thread Thread;
public readonly ManualResetEvent Completed = new ManualResetEvent(false);
public volatile Exception Exception;
public volatile bool Aborted;
public void Abort()
{
if (!Aborted)
{
Aborted = true;
try { Thread.Abort(); }
catch { }
}
}
}
...全文
914 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
於黾 2014-12-31
  • 打赏
  • 举报
回复
引用 8 楼 yang1216 的回复:
[quote=引用 5 楼 Z65443344 的回复:] 不要乱用Thread.Abort(),可能会导致线程还没有释放连接,你就把它强制结束掉了 你应该设置超时时间,如果超时就抛异常,然后你用try,catch捕获异常进行后续处理
主要是因为有时候connect本身就要挺长时间的,例如server关机,tcpclient要过很长时间才抛出异常。所以只好一定时间没完成就直接abort掉线程。[/quote] 反正是线程而已,它在后台继续运行去呗,又不影响你的主线程,为什么非要强制abort掉? 你可以设置个标识位,如果超时了,那么设置它为true,然后主线程开始执行其他逻辑,线程里如果超时抛异常,判断如果标识位是true,则不将异常抛出,直接退出线程.
yang1216 2014-12-31
  • 打赏
  • 举报
回复
引用 12 楼 Z65443344 的回复:
这就好比你派个人去门卫看是否有快递 这人去了1分钟没回来,你就给他打电话告诉他:别等了,赶紧干活去吧 然后他前脚刚走,你马上又派一个人去看 这是要闹哪样啊,让前一个人别走,继续在那等等不行吗
有道理。谢谢。
於黾 2014-12-31
  • 打赏
  • 举报
回复
这就好比你派个人去门卫看是否有快递 这人去了1分钟没回来,你就给他打电话告诉他:别等了,赶紧干活去吧 然后他前脚刚走,你马上又派一个人去看 这是要闹哪样啊,让前一个人别走,继续在那等等不行吗
於黾 2014-12-31
  • 打赏
  • 举报
回复
"下一秒再次试图连接server",这没有意义 既然你前一个已经在连接,而且还没有连接上,重新开一个线程去连接作甚?继续等待前一个线程连接不就得了
yang1216 2014-12-31
  • 打赏
  • 举报
回复
引用 9 楼 Z65443344 的回复:
[quote=引用 8 楼 yang1216 的回复:] [quote=引用 5 楼 Z65443344 的回复:] 不要乱用Thread.Abort(),可能会导致线程还没有释放连接,你就把它强制结束掉了 你应该设置超时时间,如果超时就抛异常,然后你用try,catch捕获异常进行后续处理
主要是因为有时候connect本身就要挺长时间的,例如server关机,tcpclient要过很长时间才抛出异常。所以只好一定时间没完成就直接abort掉线程。[/quote] 反正是线程而已,它在后台继续运行去呗,又不影响你的主线程,为什么非要强制abort掉? 你可以设置个标识位,如果超时了,那么设置它为true,然后主线程开始执行其他逻辑,线程里如果超时抛异常,判断如果标识位是true,则不将异常抛出,直接退出线程.[/quote] 我希望下一秒还要再次试图连接server,这样什么时候server恢复都能很快重建连接。如果不abort这个线程,在connect报超时异常所需的那20s内,就会有20个线程都在那儿试着连接。而我可能会有每秒很多个server需要访问,这样就会有非常多个试图连接的线程了。
yang1216 2014-12-30
  • 打赏
  • 举报
回复
引用 5 楼 Z65443344 的回复:
不要乱用Thread.Abort(),可能会导致线程还没有释放连接,你就把它强制结束掉了 你应该设置超时时间,如果超时就抛异常,然后你用try,catch捕获异常进行后续处理
主要是因为有时候connect本身就要挺长时间的,例如server关机,tcpclient要过很长时间才抛出异常。所以只好一定时间没完成就直接abort掉线程。
yang1216 2014-12-30
  • 打赏
  • 举报
回复
再补充一下: server那边是别人的一个dsp设备,我没法改。 这个要实现长连接怎么做呀?
yang1216 2014-12-30
  • 打赏
  • 举报
回复
引用 6 楼 Pc498471249 的回复:
你没有开启服务端
服务端当然开启了,正常通讯300多次呢。
yang1216 2014-12-30
  • 打赏
  • 举报
回复
引用 2 楼 wjq 的回复:
既然是tcp链接,你又为什么要搞那么碎的链接?tcp就是用来搞可靠性的长链接的。碎片化的短暂链接考虑一下udp协议。 不知道你server的实现,可能端口用完了,或者对于短时间内重复访问有限制等等。不论如何,每秒一次重复性链接用tcp协议肯定是不合适的
谢谢。第一次做tcp的东西,长链接不会呀。 我百度一下试试。
Pc498471249 2014-12-30
  • 打赏
  • 举报
回复
你没有开启服务端
於黾 2014-12-30
  • 打赏
  • 举报
回复
不要乱用Thread.Abort(),可能会导致线程还没有释放连接,你就把它强制结束掉了 你应该设置超时时间,如果超时就抛异常,然后你用try,catch捕获异常进行后续处理
wjq 2014-12-30
  • 打赏
  • 举报
回复
既然是tcp链接,你又为什么要搞那么碎的链接?tcp就是用来搞可靠性的长链接的。碎片化的短暂链接考虑一下udp协议。 不知道你server的实现,可能端口用完了,或者对于短时间内重复访问有限制等等。不论如何,每秒一次重复性链接用tcp协议肯定是不合适的
yang1216 2014-12-29
  • 打赏
  • 举报
回复
补充: 所有的IP都是127.0.0.1,所以不会是ip没写对的问题。 补充2: 我发现netstat有很多CLOSE_WAIT,FIN_WAIT_2。会是它们的问题吗? 协议 本地地址 外部地址 状态 TCP 127.0.0.1:3100 edusoho-rc:40796 CLOSE_WAIT TCP 127.0.0.1:3100 edusoho-rc:40797 CLOSE_WAIT TCP 127.0.0.1:3100 edusoho-rc:40864 CLOSE_WAIT 。。。还有很多个。。。 TCP 127.0.0.1:3100 edusoho-rc:40865 ESTABLISHED TCP 127.0.0.1:3100 edusoho-rc:40866 ESTABLISHED TCP 127.0.0.1:32919 edusoho-rc:33000 ESTABLISHED TCP 127.0.0.1:33000 edusoho-rc:32919 ESTABLISHED TCP 127.0.0.1:40796 edusoho-rc:3100 FIN_WAIT_2 TCP 127.0.0.1:40823 edusoho-rc:3100 FIN_WAIT_2 TCP 127.0.0.1:40824 edusoho-rc:3100 FIN_WAIT_2 。。。还有很多个。。。

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧