c# socket開了receive執行緒,然后死回圈接收資料,while(true){ ..... }按理說會一直回圈接收資料,打斷點會隨時停住,但我這的情況是過一會斷點就不進來了,server每10秒發一次心跳包,剛開始是可以接收資料的,過幾分鐘或者十幾分鐘(時間每次不一樣),就進不到這個死回圈里了,也不接收資料了,這個是怎么回事?但是TCP工具是可以收到的。
代碼如下:
tcp = new Thread(new ThreadStart(ProcessData));
tcp.Start();
private void ProcessData()
{
byte[] tmp_package;
while (true)
{
try
{
byte[] tmp = new byte[20000];
int recv = socket.Receive(tmp);
byte[] radar = new byte[recv];
Buffer.BlockCopy(tmp, 0, radar, 0, recv);
RadarPackageList.Add(radar);
_writeListIndex++;
while (_writeListIndex > 0)
{
lock (RadarPackageList)
{
tmp_package = RadarPackageList[0];
RadarPackageList.RemoveAt(0);
_writeListIndex--;
}
string rcvString = System.Text.Encoding.UTF8.GetString(tmp_package);
string s2 = rcvString.Substring(startIndex, rcvString.Length - startIndex);
if (!s2.Contains("direction_finding") || startIndex <=0)
{
Console.WriteLine("心跳資料-----------------------" + DateTime.Now.ToString());
continue;
}
}
}
}
}
catch (Exception ex)
{
}
}
uj5u.com熱心網友回復:
代碼不對。ACCEPT這東西在WHILE就行了。uj5u.com熱心網友回復:
請教代碼哪里不對?剛開始運行時是可以的,過段時間Console.WriteLine("心跳資料-----------------------" + DateTime.Now.ToString());這句話就不列印了,在while死回圈里打斷點也進不來了uj5u.com熱心網友回復:
沒錯啊,你吃例外了。例外了執行緒不就自然退出了么?uj5u.com熱心網友回復:
我在catch里列印了一句話,程式沒有跳到例外里面,那個心跳提示列印著就不列印了,況且try....catch在 while(true)里面,就算跳到catch里,也不應該跳出while(true)吧
uj5u.com熱心網友回復:
那你這么寫, Console.WriteLine("while 運行中-----------------------" + DateTime.Now.ToString()); 放到while的下一句看看在你說不列印的情況下,while是否真的還在while
話說 不列印那句話,還不代表while不允許,只代表 if (!s2.Contains("direction_finding") || startIndex <=0) 條件木達到
至于沒達到的原因么,也很簡單。這代碼是靠巧合運行。依賴的邏輯是,碰巧每次能收到 direction_finding,既然是靠巧合運行,那么也可以是碰巧N分鐘以后有一個錯位,每次收到都沒有direction_finding他
也許是連續3次收到的是
direction_findin
gdirection_
_findingdire
uj5u.com熱心網友回復:
不一定是這段代碼的問題,你是網頁還是桌面程式?網頁的話,這段話是放在Session里還是就在網頁代碼里啟動了?uj5u.com熱心網友回復:
是控制臺程式
uj5u.com熱心網友回復:
在 int recv = socket.Receive(tmp); 陳述句后增加列印 tmp 的內容代碼,看看是不是發生粘包、拆包了。uj5u.com熱心網友回復:
-------------------------------------------------
粘包、拆包會對socket接收資料有影響嗎?
假如發生了粘包、拆包,有解決辦法嗎?
uj5u.com熱心網友回復:
Socket.Receive()的超時問題uj5u.com熱心網友回復:
超時了就不會再接收資料了嗎?server每10秒發一次心跳包,10秒不算長啊
uj5u.com熱心網友回復:
-----------------------------------------
按照您的方法試了下,將Console.WriteLine("while 運行中-----------------------")這句話放在while(true)下,運行了2次,第一次運行了一個多小時都一直正常,關閉后重新運行一次程式,運行了20多分鐘不動了,什么都不列印了,在while(true)里打斷點也不行

uj5u.com熱心網友回復:
那就是你那個執行緒已經掛了那就 Application.ThreadException+= 事件
掛接ThreadException例外事件,看看到底執行緒為啥掛。
ps:如果專案剛啟動,我個人建議你直接換成dotnetty把。dotnettyclient也沒幾行代碼
group = new MultithreadEventLoopGroup(3);
bootstrap = new Bootstrap();
bootstrap
.Group(group)
.Channel<TcpSocketChannel>() //使用tcp協議
.Option(ChannelOption.TcpNodelay, true)
.Option(ChannelOption.ConnectTimeout, TimeSpan.FromSeconds(3)) //連接超時定義
.Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
{
//初始化訊息管道
IChannelPipeline pipeline = channel.Pipeline;
//斷線重連
pipeline.AddLast(new MonitorTcpBreakHandler()); //MonitorTcpBreakHandler這是自己的東西,主要處理斷線邏輯
// IdleStateHandler 心跳保活
pipeline.AddLast("timeout", new IdleStateHandler(0, MonitorApiConfig.Instance.TcpConfig.IdleInterval, 0)); //這也是自己的邏輯主要處理空閑心跳
//上面兩個都是一些業務邏輯處理,要不要自己實作看業務要求
pipeline.AddLast(new LineBasedFrameDecoder(1024 * 1024)); //此處是跟你相關的邏輯,也就是讀以回車換行分割的封包,最大包大小1M
pipeline.AddLast(new StringDecoder(Encoding.UTF8)); //接到封包后,下一級管道,用utf8解碼
pipeline.AddLast("tcp", new monitorTcpClientHandler()); //最后你得實際接收處理模塊,也是最重要的模塊
pipeline.AddLast(new MonitorTcpIdleHandler()); //處理接收,發送空閑保活邏輯
}));
clientChannel = await bootstrap.ConnectAsync(
new IPEndPoint(ip, port)
);
后面這個我就只抽核心邏輯了(畢竟專案業務邏輯,不能貼出來了)
public class monitorTcpClientHandler : ChannelHandlerAdapter
{
//經過上面一串處理管道,最終到這里就是決議好的,可以直接使用的封包,前面已經有兩個管道,幫你處理粘包/拆包,幫你轉換成utf8字串,所以現在可以直接用的
public override void ChannelRead(IChannelHandlerContext context, object message)
{
string str = (string)message;
LogHelper.info($"接收tcp訊息{str}");
}
}
uj5u.com熱心網友回復:
socket 只負責收發資料,socket 不是發送方發送一次,接收方就能全部一次接受完全,受作業系統以及緩沖區大小的影響,會發生拆包、粘包問題,socket 并不負責處理這類問題。如果使用較好的三方框架類別庫,框架類別庫會幫你處理好這些問題,否則你需要自己處理。
粘包、拆包詳情請自行百度。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/3725.html
標籤:C#
