我在C#中的.Net套接字中遇到了一些問題。 我編寫了一個客戶端和一個使用TCP的服務器。C#.Net套接字服務器客戶端
當客戶端打開時,它向服務器發送握手。服務器回答它的狀態(客戶端,客戶端,...)。之後,應用程序發送getdata請求,放棄連接並監聽服務器的「響應」。現在,服務器建立到客戶端的連接併發送客戶端需要的所有數據。
的代碼和其他一切工作,但問題:
在我們公司TESTSERVER它工作正常,直播服務器只握手工作在。之後,客戶端不會再收到任何數據。 Servepplication在兩臺服務器上都是一樣的。
我認爲這個問題是由一些防火牆引起的(服務器想建立到客戶端的tcp連接 - >不好),但是系統管理員說沒有防火牆可以阻止這個問題。
現在我正在尋找一種不需要太多時間和代碼更改的('便宜')解決方案。如果有人知道如何從理論上解決這個問題,那就太好了。
BTW:除了運行服務器應用程序,我不允許在活服務器上執行任何操作。我無法在此服務器上進行調試。
我無法發佈我的所有代碼,但如果您需要查看它的特定部分,請索取。
---編輯---
客戶端服務器通信
1)客戶端啓動
客戶端發送握手(新的TCP連接)
2)服務器驗證握手,並節省IP
服務器迴應它的客戶端狀態(相同的TCP連接)
3)客戶端確認此響應並放棄此連接
客戶端發送getdata-request(新的tcp連接)
客戶端放棄該TCP連接,過於
4)服務器接收的GetData請求並收集在主數據庫
5)客戶端接收所有需要的數據
服務器所有所收集的數據發送到客戶端(多個TCP連接)數據並顯示它在它的GUI
這是最主要的部分我的代碼做(多個TCP連接和數據的順序是由與插座的AutoResetEvents並計數派工作保持)。這是迄今爲止不是最好的,但我認爲這是我寫的。第一步,第二步和第三步按預期工作。數據的處理也可以正常工作。 我忘記提及的另一件事是解決方案使用兩個端口'16777'和'16778'。一個收/聽,一個發送。 我的代碼基於異步server和client的MSDN示例。
發送握手(和的GetData請求)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
服務器監聽
public void StartListening()
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(System.Int32.MaxValue);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
插槽發送
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
套接字發送的所有數據部分(答案的GetData請求| socToHandle應該是getdata請求的上一個連接的套接字)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
翻翻我的舊代碼,我有一個想法=>
我能否通過改變發送一切通過相同的連接:
的Socket T = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint) 。地址);
(這將創建一個新的連接)的東西,使用相同的連接? 如果這可行,我該怎麼做? 客戶端的偵聽器部分仍然會收到單個數據包嗎?
假設系統管理員在於。 嘗試使用https://technet.microsoft.com/en-us/sysinternals/jj729731.aspx端口上運行服務器和測試連接。上傳試圖ping您的客戶端IP的代碼版本。 也雙方都應該經常測試防火牆/連接問題並記錄它們。 – Nahum
您不必向我們展示「我的所有代碼」 - 事實上,這樣做會適得其反。 *會有用的是你創建一個[MCVE](http://stackoverflow.com/help/mcve)。 –
TCP實現中的常見錯誤與處理接收到的流有關。接收過程必須考慮到可能在不同的塊中接收到發送請求。需要使用長度值方法或使用分隔符來封裝發送數據,例如, STX和ETX。 – Graffito