[英]C# TcpClient not sending or reading 100% of data?
大家好。 我正在編寫一個簡單的客戶端/服務器應用程序(就經驗而言,聯網對我來說還很新),客戶端在其中發送服務器數據,然后服務器將其輸出到文本框。 一切正常,除了一個小細節...似乎有時建立了連接,但是沒有發送或讀取數據(無法計算出哪個),因此文本框中未輸出任何內容。 每次建立連接時,計數器都會增加,接收數據塊時也是如此。 當您將兩者進行比較時,連接數是正確的,但數據計數器通常較低,有時多達一半。 無論如何,如果有人可以給我一些建議或指出正確的方向,將不勝感激!
如果需要的話,下面是代碼:
(SERVER_CODE)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Server
{
public partial class Form1 : Form
{
public int Connections = 0;
public int blocks = 0;
public int threads = 0;
public Thread MasterThread;
public TcpListener Master;
public volatile bool Run;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void StartMaster()
{
Master = new TcpListener(IPAddress.Any, 1986);
Master.Start();
MasterThread = new Thread(new ThreadStart(RunMaster));
MasterThread.Start();
}
public void RunMaster()
{
threads++;
label6.Text = String.Format("{0}", threads);
while (Run)
{
TcpClient client = Master.AcceptTcpClient();
Connections++;
label4.Text = String.Format("{0}", Connections);
Thread ClientThread = new Thread(new ParameterizedThreadStart(RunClient));
ClientThread.Start(client);
}
Master.Stop();
threads--;
label6.Text = String.Format("{0}", threads);
}
public void RunClient(object tcpClient)
{
TcpClient client = (TcpClient)tcpClient;
byte[] buffer = new byte[4096];
int byteCount = 0;
NetworkStream stream = client.GetStream();
threads++;
label6.Text = String.Format("{0}", threads);
while (Run)
{
try
{
byteCount = stream.Read(buffer, 0, 4096);
}
catch
{
//Connections--;
break;
}
if (byteCount == 0)
{
//Connections--;
break;
}
blocks++;
label5.Text = String.Format("{0}", blocks);
textBox1.AppendText(Encoding.ASCII.GetString(buffer, 0, byteCount) + "\r\n");
}
client.Close();
threads--;
label6.Text = String.Format("{0}", threads);
}
private void button1_Click(object sender, EventArgs e)
{
Run = true;
StartMaster();
}
private void button2_Click(object sender, EventArgs e)
{
Run = false;
}
}
}
(CLIENT_CODE)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1986);
TcpClient client = new TcpClient();
try
{
client.Connect(endPoint);
}
catch
{
MessageBox.Show("Connect Error");
}
NetworkStream stream = client.GetStream();
byte[] data = Encoding.ASCII.GetBytes(textBox1.Text);
stream.Write(data, 0, data.Length);
stream.Flush();
client.Close();
}
}
}
謝謝,
特里斯坦!
好吧,首先,您要破壞自己的診斷程序:
catch
{
//Connections--;
break;
}
為什么在沒有任何日志記錄的情況下吞下異常? 可能會引發異常,您無法知道。 理想情況下你應該捕獲特定的異常,而當你捕捉異常至少登錄是怎么回事。
另一方面, Wireshark應該幫助您確定是否正在發送數據。
我還沒有徹底了解您的代碼,但是快速瀏覽后,您可以在沒有適當鎖定的情況下從多個線程訪問變量。 像x++;
這樣的語句x++;
必須讀取x
的值,對其進行遞增並寫回。 現在,如果有兩個線程執行此操作,則可能會遇到這種情況:
x = 0
Thread 1 Thread 2
------------------------
Read (0)
Read (0)
Increment (1)
Increment (1)
Write (1)
Write (1)
=> x = 1 instead of 2
如果您需要從多個線程訪問變量,請始終進行同步,除非您確切地知道自己在做什么。 例如,創建並使用如下所示的同步對象:
int threads = 0;
object threadSync = new object();
...
lock (threadSync) {
threads++;
}
然后一次只能有一個線程訪問該變量,並且值會正確遞增。
編輯:另一個問題是您從與創建控件不同的線程訪問可見控件。 早期的.NET版本允許這樣做,但較新的版本不允許。 如果需要更新狀態消息,則需要查看控件的InvokeRequired
屬性,如果將其設置為true,請使用Control.Invoke(...)調用設置該屬性的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.