我有一個應用程序爲我的應用程序編寫,分佈在整個公司,通過我們的Windows 2003服務器(運行IIS 6.0)向我發送數據。小文本消息可以通過,但包含更多數據(大約20 KB)的大消息無法通過。TCP客戶端連接
我將字節緩衝區設置爲TCP客戶端的緩衝區大小。我注意到我的數據正在服務器上收到;但是,它只通過接收例程循環一次,而我的大文件總是正好是緩衝區大小的大小,或者我們服務器上的大小爲8 KB。換句話說,我的代碼只在服務器關閉套接字連接之前通過一個循環。
考慮到填充整個緩衝區可能存在問題,我嘗試將讀/寫限制爲1 KB,但這僅導致我們的服務器在關閉連接之前收到1 KB後關閉套接字。
我將服務器的錯誤信息發送回客戶端,以便我可以查看它。我從客戶端收到特定的錯誤信息是:
「Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.」
我更新了我的服務器應用程序,使底層TCP套接字將使用的「保持活動」這一行:
client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
現在,每當我試圖發送一個消息,在客戶端收到錯誤:
「Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.」
我們的網絡管理員告訴我,他沒有防火牆或阻止我們內部的服務器上的任意端口。
使用谷歌搜索錯誤,我發現帖子暗示人們嘗試遠程登錄到服務器。我用自己的方向遠程登錄到服務器上,但我不知道該做出響應的是什麼:
C:> telnet Welcome to Microsoft Telnet Client
Escape Character is ‘CTRL+]’
Microsoft Telnet> open cpapp 500 Connecting To cpapp…
這是我得到的。我從來沒有得到一個錯誤,微軟的Telnet屏幕最終會改變爲「按任意鍵繼續......」 - 我猜測它超時了,但我的代碼以某種方式能夠連接。
我已經嘗試了代碼中的其他端口,並通過Telnet包括25,80,8080.Telnet踢出端口25,但我的應用程序似乎讀取第一個循環,不管我告訴它運行哪個端口。
這裏是我的代碼,在客戶端上運行:
int sendUsingTcp(string location) {
string result = string.Empty;
try {
using (FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read)) {
using (TcpClient client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) {
byte[] riteBuf = new byte[client.SendBufferSize];
byte[] readBuf = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream()) {
if ((ns.CanRead == true) && (ns.CanWrite == true)) {
int len;
string AOK = string.Empty;
do {
len = fs.Read(riteBuf, 0, riteBuf.Length);
ns.Write(riteBuf, 0, len);
int nsRsvp = ns.Read(readBuf, 0, readBuf.Length);
AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp);
} while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK")));
result = AOK;
return 1;
}
return 0;
}
}
}
} catch (Exception err) {
Logger.LogError("Send()", err);
MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0);
return -1;
}
}
這裏是我的代碼在服務器上運行:
SvrForm.Server = new TcpListener(IPAddress.Any, CpAppDatabase.ServerPortNumber);
void Worker_Engine(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = sender as BackgroundWorker;
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.CompanyName);
if (Directory.Exists(path) == false) Directory.CreateDirectory(path);
Thread.Sleep(0);
string eMsg = string.Empty;
try {
SvrForm.Server.Start();
do {
using (TcpClient client = SvrForm.Server.AcceptTcpClient()) { // waits until data is avaiable
if (worker.CancellationPending == true) return;
client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
string location = Path.Combine(path, string.Format("Acp{0:yyyyMMddHHmmssff}.bin", DateTime.Now));
byte[] buf = new byte[client.ReceiveBufferSize];
try {
using (NetworkStream ns = client.GetStream()) {
if ((ns.CanRead == true) && (ns.CanWrite == true)) {
try {
int len;
byte[] AOK = Encoding.ASCII.GetBytes("AOK");
using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write)) {
do {
len = ns.Read(buf, 0, client.ReceiveBufferSize);
fs.Write(buf, 0, len);
ns.Write(AOK, 0, AOK.Length);
} while ((0 < len) && (ns.DataAvailable == true));
}
byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server");
ns.Write(okBuf, 0, okBuf.Length);
} catch (Exception err) {
Global.LogError("ServerForm.cs - Worker_Engine(DoWorkEvent)", err);
byte[] errBuf = Encoding.ASCII.GetBytes(err.Message);
ns.Write(errBuf, 0, errBuf.Length);
}
}
}
}
worker.ReportProgress(1, location);
}
} while (worker.CancellationPending == false);
} catch (SocketException) {
// See MSDN: Windows Sockets V2 API Error Code Documentation for detailed description of error code
e.Cancel = true;
} catch (Exception err) {
eMsg = "Worker General Error:\r\n" + err.Message;
e.Cancel = true;
e.Result = err;
} finally {
SvrForm.Server.Stop();
}
}
爲什麼沒有我的應用程序繼續從TCP客戶端閱讀?我有沒有忽視設置一些東西,告訴套接字在我完成之前保持打開狀態?服務器代碼從不會看到異常,因爲TCP客戶端從不停止,所以我知道沒有錯誤。
我們的網絡管理員還沒有收到他的同事學位,所以如果事實證明是服務器的問題,請在你的描述中詳細說明如何解決這個問題,因爲我們可能不明白你在說什麼。
我很抱歉這麼長時間,但我想確保你們在那裏知道我在做什麼 - 甚至可以從我的技術中獲得一些信息!
感謝您的幫助! 〜喬
沒有開玩笑嗎?我想現在是有道理的。我一直在想,需要在服務器上設置一些東西。這有助於很多*!謝謝! – jp2code 2009-08-12 13:06:29
我該怎麼做? 「在發送內容之前的內容長度」我沒有發送內容的長度? – 2017-11-28 08:26:48
如果你不知道長度,那麼顯然你不會發送線上的長度。 – Amy 2017-11-28 22:09:03