tcp/ip连接成功后断开网络会有什么影响?怎么解决?

sosoben 2015-11-13 12:29:48
我发现一个线性,在建立连接成功后断开了网络,这时发送是会catch到ex的,再次建立连接当然也是不行。
在接收端与发送端都维持现状的情况下,我重新接通了网络,这时无论接收端或者发送端都不会报错,这时我逐步调试过发送端是有运行下面的代码的,都是像正常一样一步步运行的,但接收端就是收不到信息

这时无论我接收端怎么关闭了重启也没用,直到重起了接收端的程序才解决这个问题。

请问是为什么呢?怎么解决??


发送部分代码如下
public void send(string ip, int port, string str)
{
try
{
IPAddress ipadd = IPAddress.Parse(ip);
TcpClient tcpc = TimeOutSocket.Connect(new IPEndPoint(ipadd, port), 6000);
\\就是在这里,建立连接成功后断开了网络
NetworkStream tcpstream = tcpc.GetStream();
byte[] data = Encoding.Unicode.GetBytes(str);
tcpstream.Write(data, 0, data.Length);
tcpstream.Close();
tcpc.Close();

}
catch (Exception ex)
{
throw ex;
}
}


接受部分代码
public void Listen()
{
try {
IPAddress[] addr = Dns.GetHostAddresses(Dns.GetHostName());
int IPnum = 0;
for (i = 0; i <= addr.Length - 1; i++) {
if (addr(i).ToString // ERROR: Unknown binary operator Like
) {
IPnum = i;
}
}
IPEndPoint iplocalendpoint = new IPEndPoint(addr(IPnum), Netport);
tcpl = new TcpListener(iplocalendpoint);
tcpl.Start();
listernerRun = true;
while (listernerRun) {
Socket s = tcpl.AcceptSocket;
string remote = s.RemoteEndPoint.ToString;
byte[] stream = new byte[1025];
int i = s.Receive(stream);
Array.Resize(ref stream, i);
string msg = Encoding.UTF8.GetString(stream);
//"<" + remote + ">" +
AddMessageEventarge arg = new AddMessageEventarge();
arg.mess = msg;
if (OnAddMessage != null) {
OnAddMessage(this, arg);
}
}
}
catch (Exception ex)
{
throw ex;
}
}


...全文
767 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
sosoben 2015-11-20
  • 打赏
  • 举报
回复
引用 19 楼 Tidal_Choidi 的回复:
[quote=引用 17 楼 sosoben 的回复:] [quote=引用 16 楼 Tidal_Choidi 的回复:] 长连接还是短连接?是否需要有心跳包的检测?
什么是长连接,什么是短连接?我是一直listen,那应该是长连接吧。 心跳包也是我考虑的范围,但是不知道影不影响性能呢? 因为有十几台机同时连主机,主机要根据接收到的信息进行记录数据,查询数据等一系列任务,主机也不是服务器级别的[/quote] =============================================================================================== 长连接/短连接--->http://www.cnblogs.com/liuyong/archive/2011/07/01/2095487.html 心跳包,TCP协议自身本来已经提供这种机制了,但是这种检测的时间间隔是2h,这样的效率的确不行,因此需要在应用层上自己完成心跳包的实现。至于性能,应该不会有太打的影响滴。[/quote] 谢谢,按照网址中的说法,我的应该是短连接了。应为每次客户端要发送就new 一个 TcpClient,发送完后退出 这样是不是不好呢? 我的机器基本一天到晚开着的。 那心跳包是每个客户端都会定时向服务端发送数据,如果一段时间全都收不到就重启自己的listen 服务器端也定时向每个客户端发送数据,如果客户端接受不到,也是重启自己的listen,对吗?
public void send(string ip, int port, string str)
{
    try 
       {
        IPAddress ipadd = IPAddress.Parse(ip);
        TcpClient tcpc = TimeOutSocket.Connect(new IPEndPoint(ipadd, port), 6000);
\\就是在这里,建立连接成功后断开了网络
        NetworkStream tcpstream = tcpc.GetStream();
        byte[] data = Encoding.Unicode.GetBytes(str);
        tcpstream.Write(data, 0, data.Length);
        tcpstream.Close();
        tcpc.Close();
 
    } 
catch (Exception ex)
       {
        throw ex;
    }
}
  • 打赏
  • 举报
回复
用我说的方法应该解决问题了吧? TCPClient和Socket都可以使用,TCPClient只是将Socket进行了一定的封装,使用起来更简单,如果TCPClient已经满足了你的要求,就用它就行,Socket更底层一些,可以设置更多的参数。
Tidal_Choidi 2015-11-20
  • 打赏
  • 举报
回复
引用 17 楼 sosoben 的回复:
[quote=引用 16 楼 Tidal_Choidi 的回复:] 长连接还是短连接?是否需要有心跳包的检测?
什么是长连接,什么是短连接?我是一直listen,那应该是长连接吧。 心跳包也是我考虑的范围,但是不知道影不影响性能呢? 因为有十几台机同时连主机,主机要根据接收到的信息进行记录数据,查询数据等一系列任务,主机也不是服务器级别的[/quote] =============================================================================================== 长连接/短连接--->http://www.cnblogs.com/liuyong/archive/2011/07/01/2095487.html 心跳包,TCP协议自身本来已经提供这种机制了,但是这种检测的时间间隔是2h,这样的效率的确不行,因此需要在应用层上自己完成心跳包的实现。至于性能,应该不会有太打的影响滴。
sosoben 2015-11-20
  • 打赏
  • 举报
回复
引用 15 楼 ShelleyLiu0415 的回复:
[quote=引用 12 楼 sosoben 的回复:] [quote=引用 10 楼 ShelleyLiu0415 的回复:] 给Server端的程序加一个Socket Receive的Timeout时间,默认是无穷大;另外,Server端的程序,While语句里应该 加一个Try catch,避免某个Socket出问题导致整个Server端程序退出。
请问Socket Receive的Timeout时间 是怎么设的呢? 是s.ReceiveTimeout 吗? 就是说一段时间 s.Receive(stream) 收不到东西就跳出,进行下一次的while循环,这样是吗?
Public Sub Listen()
            Try
                Dim addr() As IPAddress = Dns.GetHostAddresses(Dns.GetHostName())
                Dim IPnum As Integer
                For i = 0 To addr.Length - 1
                    If addr(i).ToString Like "192.168.100.*" Then
                        IPnum = i
                    End If
                Next
                Dim iplocalendpoint As IPEndPoint = New IPEndPoint(addr(IPnum), Netport)
                tcpl = New TcpListener(iplocalendpoint)
                tcpl.Start()
                listernerRun = True
                While listernerRun
                    Dim s As Socket = tcpl.AcceptSocket
                    Dim remote As String = s.RemoteEndPoint.ToString
                    Dim stream(1024) As Byte
                    Try
                        s.ReceiveTimeout = 10000
                    Catch ex As Exception

                    End Try

                    Dim i As Integer = s.Receive(stream)
                    ReDim Preserve stream(i - 1)
                    Dim msg As String = Encoding.UTF8.GetString(stream) '"<" + remote + ">" + 
                    Dim arg As AddMessageEventarge = New AddMessageEventarge()
                    arg.mess = msg
                    RaiseEvent OnAddMessage(Me, arg)
                End While
            Catch ex As Exception
                'Throw ex 'My.Computer.FileSystem.WriteAllText(Application.StartupPath & "\错误报告\ClassListenner错误报告.txt", Now & " " & ex.Message & vbNewLine, True)

            End Try
        End Sub
[/quote] 对,就是s.ReceiveTimeout这个属性。 “就是说一段时间 s.Receive(stream) 收不到东西就跳出,进行下一次的while循环,这样是吗? ” 对的,这样才会导致你的主程序不会hang住,或者你可以监听到一个Socket出来之后,就马上启动一个线程去做事,在线程里面再去Read data,这样也不会导致阻塞主监听程序。 PS. 怎么突然又从C#跳到VB了。:D[/quote] 哈哈,我用VB项目又做了试验,一时忘记了转回来。 还想问一下,我这样的代码是不是太基础了点,我上网查了下TCP/ip的实现方法,发现有很多,有的用socket,有的用tcpclient。 有的用Socket.Receive ,有的用Tcpclient.GetStream,有什么区别啊? 请问有没有比较通用的标准的方法推荐啊?
sosoben 2015-11-20
  • 打赏
  • 举报
回复
引用 16 楼 Tidal_Choidi 的回复:
长连接还是短连接?是否需要有心跳包的检测?
什么是长连接,什么是短连接?我是一直listen,那应该是长连接吧。 心跳包也是我考虑的范围,但是不知道影不影响性能呢? 因为有十几台机同时连主机,主机要根据接收到的信息进行记录数据,查询数据等一系列任务,主机也不是服务器级别的
sosoben 2015-11-20
  • 打赏
  • 举报
回复
[quote=引用 20 楼 ShelleyLiu0415 的回复:] 用我说的方法应该解决问题了吧? TCPClient和Socket都可以使用,TCPClient只是将Socket进行了一定的封装,使用起来更简单,如果TCPClient已经满足了你的要求,就用它就行,Socket更底层一些,可以设置更多的参数。[/quote 是的,上述问题解决了。 立刻就给分,哈哈!但我觉得心跳也是有点道理的,但我没有作具体试验所以不知道怎么给分。
  • 打赏
  • 举报
回复
引用 12 楼 sosoben 的回复:
[quote=引用 10 楼 ShelleyLiu0415 的回复:] 给Server端的程序加一个Socket Receive的Timeout时间,默认是无穷大;另外,Server端的程序,While语句里应该 加一个Try catch,避免某个Socket出问题导致整个Server端程序退出。
请问Socket Receive的Timeout时间 是怎么设的呢? 是s.ReceiveTimeout 吗? 就是说一段时间 s.Receive(stream) 收不到东西就跳出,进行下一次的while循环,这样是吗?
Public Sub Listen()
            Try
                Dim addr() As IPAddress = Dns.GetHostAddresses(Dns.GetHostName())
                Dim IPnum As Integer
                For i = 0 To addr.Length - 1
                    If addr(i).ToString Like "192.168.100.*" Then
                        IPnum = i
                    End If
                Next
                Dim iplocalendpoint As IPEndPoint = New IPEndPoint(addr(IPnum), Netport)
                tcpl = New TcpListener(iplocalendpoint)
                tcpl.Start()
                listernerRun = True
                While listernerRun
                    Dim s As Socket = tcpl.AcceptSocket
                    Dim remote As String = s.RemoteEndPoint.ToString
                    Dim stream(1024) As Byte
                    Try
                        s.ReceiveTimeout = 10000
                    Catch ex As Exception

                    End Try

                    Dim i As Integer = s.Receive(stream)
                    ReDim Preserve stream(i - 1)
                    Dim msg As String = Encoding.UTF8.GetString(stream) '"<" + remote + ">" + 
                    Dim arg As AddMessageEventarge = New AddMessageEventarge()
                    arg.mess = msg
                    RaiseEvent OnAddMessage(Me, arg)
                End While
            Catch ex As Exception
                'Throw ex 'My.Computer.FileSystem.WriteAllText(Application.StartupPath & "\错误报告\ClassListenner错误报告.txt", Now & " " & ex.Message & vbNewLine, True)

            End Try
        End Sub
[/quote] 对,就是s.ReceiveTimeout这个属性。 “就是说一段时间 s.Receive(stream) 收不到东西就跳出,进行下一次的while循环,这样是吗? ” 对的,这样才会导致你的主程序不会hang住,或者你可以监听到一个Socket出来之后,就马上启动一个线程去做事,在线程里面再去Read data,这样也不会导致阻塞主监听程序。 PS. 怎么突然又从C#跳到VB了。:D
  • 打赏
  • 举报
回复
对,就是s.ReceiveTimeout这个属性。 “就是说一段时间 s.Receive(stream) 收不到东西就跳出,进行下一次的while循环,这样是吗? ” 对的,这样才会导致你的主程序不会hang住,或者你可以监听到一个Socket出来之后,就马上启动一个线程去做事,在线程里面再去Read data,这样也不会导致阻塞主监听程序。 PS. 怎么突然又从C#跳到VB了。:D
冰冷的小爪 2015-11-19
  • 打赏
  • 举报
回复
尝试用心跳看看,网络断开后Send报错,然后重新等待客户端
sosoben 2015-11-19
  • 打赏
  • 举报
回复
请问Socket Receive的Timeout时间 是怎么设的呢? 就是说一段时间 s.Receive(stream) 收不到东西就跳出,进行下一次的while循环,是吗?
Tidal_Choidi 2015-11-19
  • 打赏
  • 举报
回复
长连接还是短连接?是否需要有心跳包的检测?
  • 打赏
  • 举报
回复
给Server端的程序加一个Socket Receive的Timeout时间,默认是无穷大;另外,Server端的程序,While语句里应该 加一个Try catch,避免某个Socket出问题导致整个Server端程序退出。
sosoben 2015-11-14
  • 打赏
  • 举报
回复
开线程的语句如下,在一个异步ping的返回事件里,如果ping通则触发

ScanPlan class1 = new ScanPlan(i);
Thread th = new Thread(class1.sendPlan);
th.Start();

sosoben 2015-11-14
  • 打赏
  • 举报
回复
引用 7 楼 sosoben 的回复:
[quote=引用 6 楼 wmy_03 的回复:] 写了Demo,没有复现你说的问题
引用
这时无论我接收端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。
这句没明白,你是想说“这时无论我发送端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。”吗
是啊,是这个意思,又笔误了。你的demo,是一接通网络就立刻可以用了吗? 难道是我外面的程序有问题? 我是用一个timer吧 时间一到就或者条件合适就发送
TCP.ClassSender tcpsender = new TCP.ClassSender();
foreach (DataRow row in ds.Tables(0).Rows) {
	tcpsender.send(IPArray(jitai), 5657, "90|" + row(0) + "|" + Convert.ToDateTime(row(2)).ToString("yyyy/MM/dd HH:mm:ss") + "|" + row(3));
	Threading.Thread.Sleep(20);
}
Threading.Thread.Sleep(20);
tcpsender.send(IPArray(jitai), 5657, "91|over");

[/quote] 还有,上面这段代码是新开了个线程运行的
sosoben 2015-11-14
  • 打赏
  • 举报
回复
引用 6 楼 wmy_03 的回复:
写了Demo,没有复现你说的问题
引用
这时无论我接收端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。
这句没明白,你是想说“这时无论我发送端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。”吗
是啊,是这个意思,又笔误了。你的demo,是一接通网络就立刻可以用了吗? 难道是我外面的程序有问题? 我是用一个timer吧 时间一到就或者条件合适就发送
TCP.ClassSender tcpsender = new TCP.ClassSender();
foreach (DataRow row in ds.Tables(0).Rows) {
	tcpsender.send(IPArray(jitai), 5657, "90|" + row(0) + "|" + Convert.ToDateTime(row(2)).ToString("yyyy/MM/dd HH:mm:ss") + "|" + row(3));
	Threading.Thread.Sleep(20);
}
Threading.Thread.Sleep(20);
tcpsender.send(IPArray(jitai), 5657, "91|over");

江南小鱼 2015-11-13
  • 打赏
  • 举报
回复
你的客户端是动态ip吧,重新联网套接字会改变的。
wmy_03 2015-11-13
  • 打赏
  • 举报
回复
写了Demo,没有复现你说的问题
引用
这时无论我接收端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。
这句没明白,你是想说“这时无论我发送端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。”吗
sosoben 2015-11-13
  • 打赏
  • 举报
回复
一开始打得太急没注意语言,我修改下我的表述 我发现一个现象,在建立连接成功后断点、断开网络,这时运行到tcpstream.Write是会catch到ex的,再次运行send建立连接当然也是会抛异常。 但在接收端与发送端都维持现状的情况下,我重新接通了网络,这时无论接收端或者发送端都不会报错,我逐步调试发送端程序,发现是有运行send下面的代码的,都是像正常一样一步步运行的,但接收端就是收不到信息,也没有抛异常。 这时无论我接收端怎么关闭了重启也没用,直到重起了接收端的程序才能继续正常接收数据。 请问是为什么呢?怎么解决??
sosoben 2015-11-13
  • 打赏
  • 举报
回复
引用 2 楼 wmy_03 的回复:
[quote=引用 楼主 sosoben 的回复:] 我发现一个线性,在建立连接成功后断开了网络,这时发送是会catch到ex的,再次建立连接当然也是不行。 在接收端与发送端都维持现状的情况下,我重新接通了网络,这时无论接收端或者发送端都不会报错,这时我逐步调试过发送端是有运行下面的代码的,都是像正常一样一步步运行的,但接收端就是收不到信息。 这时无论我接收端怎么关闭了重启也没用,直到重起了接收端的程序才解决这个问题。 请问是为什么呢?怎么解决?? 发送部分代码如下
public void send(string ip, int port, string str)
{
	try 
       {
		IPAddress ipadd = IPAddress.Parse(ip);
		TcpClient tcpc = TimeOutSocket.Connect(new IPEndPoint(ipadd, port), 6000);
\\就是在这里,建立连接成功后断开了网络
		NetworkStream tcpstream = tcpc.GetStream();
		byte[] data = Encoding.Unicode.GetBytes(str);
		tcpstream.Write(data, 0, data.Length);
		tcpstream.Close();
		tcpc.Close();

	} 
catch (Exception ex)
       {
		throw ex;
	}
}
       
接受部分代码
public void Listen()
{
	try {
		IPAddress[] addr = Dns.GetHostAddresses(Dns.GetHostName());
		int IPnum = 0;
		for (i = 0; i <= addr.Length - 1; i++) {
			if (addr(i).ToString // ERROR: Unknown binary operator Like
) {
				IPnum = i;
			}
		}
		IPEndPoint iplocalendpoint = new IPEndPoint(addr(IPnum), Netport);
		tcpl = new TcpListener(iplocalendpoint);
		tcpl.Start();
		listernerRun = true;
		while (listernerRun) {
			Socket s = tcpl.AcceptSocket;
			string remote = s.RemoteEndPoint.ToString;
			byte[] stream = new byte[1025];
			int i = s.Receive(stream);
			Array.Resize(ref stream, i);
			string msg = Encoding.UTF8.GetString(stream);
			//"<" + remote + ">" + 
			AddMessageEventarge arg = new AddMessageEventarge();
			arg.mess = msg;
			if (OnAddMessage != null) {
				OnAddMessage(this, arg);
			}
		}
	} 
catch (Exception ex)
        {
		throw ex;
	}
}
读不太懂LZ的话,弱弱的问一句,接收端没有抛异常吗?[/quote] 还真没有异常,设断点也没发现进入触发事件的语句
sosoben 2015-11-13
  • 打赏
  • 举报
回复
引用 1 楼 lovelj2012 的回复:
你的客户端是动态ip吧,重新联网套接字会改变的。
不是啊,静态的,但我每次发送都会new tcpclient 有关系吗?
加载更多回复(1)

111,093

社区成员

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

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

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