2012-01-06 109 views
1

我的服務器/監聽器有ADD或沒有耐力;什麼是解藥或prodote?我的服務器/監聽器沒有真正的沙礫

該應用程序用作套接字通信的兩端。對於第一條消息(我在textBox1中輸入「Bla」,然後label1然後讀取「Bla back atcha」,但它在隨後的消息中失敗)似乎工作正常。我有一個應用程序在我的開發機器上運行,另一個在我的第二次嘗試發送郵件時發生錯誤消息(「沒有可以建立連接的原因是因爲目標機器積極拒絕它10.24.93.110:51111「)

當我在另一臺機器上啓動」服務器「實例並在命令行中運行」netstat -a「時,它表示服務器機器正在偵聽我的開發機器在端口51111上。

第一條消息通過後,顯然收到並退回,運行「netstat -a」仍顯示與我的開發機器的連接,但該狀態不再是LISTENING,而是TIME_WAIT。

然後,我嘗試通過另一條消息,我也得到了錯誤消息(如下圖表B)

附件A:源

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 
using System.Diagnostics; 

namespace testSocketSendAndReceive_Nutshell 
{ 
    public partial class Form1 : Form 
    { 
     string sJerrysIPAddr = "10.24.31.110"; 
     string sMyIPAddr = "10.24.31.128"; 
     string sThisAppFileName = string.Empty; 
     bool bThisInstanceFunctionsAsServer = false; 

     internal static Form1 MainSocketPairForm = null; 

     public Form1() 
     { 
      InitializeComponent(); 
      MainSocketPairForm = this; 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      sThisAppFileName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; 
      lblFileName.Text = sThisAppFileName; 

      // Client and Server code are here combined in one app; however, we want each instance to run as 
      // just one or the other, so (the .exe functioning as a Server should be renamed with the subString 
      // "Server" somewhere in the filename): 
      bThisInstanceFunctionsAsServer = sThisAppFileName.Contains("Server"); 
      if (bThisInstanceFunctionsAsServer) 
      { 
       new Thread(Server).Start();  // Run server method concurrently. 
       Thread.Sleep(500);    // Give server time to start. 
      } 
      btnSendMsg.Visible = !bThisInstanceFunctionsAsServer; 
     } 

     static void Client() 
     { 
      using (TcpClient client = new TcpClient(Form1.MainSocketPairForm.sJerrysIPAddr, 51111)) // err here second time 
      using (NetworkStream n = client.GetStream()) 
      { 
       BinaryWriter w = new BinaryWriter(n); 
       w.Write(Form1.MainSocketPairForm.textBox1.Text.ToString()); 
       w.Flush(); 
       Form1.MainSocketPairForm.label1.Text = new BinaryReader(n).ReadString(); 
      } 
     } 

     static void Server()  // Handles a single client request, then exits. 
     { 
      TcpListener listener = new TcpListener(IPAddress.Any, 51111); 
      listener.Start(); //Only one usage of each socket address (protocol/network address/port) is normally permitted 
      // got the above err msg with an instance running and listening on jerry's machine 
      // continues to listen even after shut down... 
      using (TcpClient c = listener.AcceptTcpClient()) 
      using (NetworkStream n = c.GetStream()) 
      { 
       string msg = new BinaryReader(n).ReadString(); 
       BinaryWriter w = new BinaryWriter(n); 
       w.Write(msg + " back atcha!"); 
       w.Flush(); // Must call Flush because we're not disposing the writer. 
      } 
      listener.Stop(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Client(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      Close(); 
     } 
    } 
} 

附件B:完整的錯誤信息

System.Net.Sockets.SocketException未處理 消息=「無法建立連接,因爲目標機器主動拒絕它」10.24.93.110:51111「 Source =」System「 錯誤碼= 10061 NativeErrorCode = 10061 堆棧跟蹤: 在System.Net.Sockets.TcpClient..ctor(字符串主機名,端口的Int32) 在testSocketSendAndReceive_Nutshell.Form1.Client()在 C:\ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutshell \ Form1中。 CS:在testSocketSendAndReceive_Nutshell.Form1.button1_Click(對象發件人,EventArgs e)在C線57 :\ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutshell \ Form1.cs中:線90在System.Windows.Forms.Control.OnClick(EventArgs的) 在系統。 Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message &米,MouseButtons按鈕,點擊的Int32) 在System.Windows.Forms.Control.WndProc(消息&米) 在System.Windows.Forms.ButtonBase.WndProc(消息&米) 在System.Windows.Forms.Button .WndProc(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息&米) 在System.Windows.Forms的.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG & msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID,Int32 reason,Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext。RunMessageLoopInner(的Int32原因, ApplicationContext的上下文) 在System.Windows.Forms.Application.ThreadContext.RunMessageLoop(的Int32原因,ApplicationContext的 上下文) 在System.Windows.Forms.Application.Run(表格的MainForm) 在testSocketSendAndReceive_Nutshell.Program 。主要()在 C:\ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutshell \ Program.cs的:線18 在System.AppDomain._nExecuteAssembly(大會組件,字串[] args) 在System.AppDomain.ExecuteAssembly(字符串assemblyFile,證據assemblySecurity,字符串[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Obje CT狀態) 在System.Threading.ExecutionContext.Run(ExecutionContext中的ExecutionContext,ContextCallback回調, 對象狀態) 在System.Threading.ThreadHelper.ThreadStart() 的InnerException:

回答

1

你需要調用client.Close()後發送回覆。需要在服務器周圍的接受邏輯的循環:

var shouldExit == false; 
while (!shouldExit) 
    using (TcpClient c = listener.AcceptTcpClient()) 
    { 
     using (NetworkStream n = c.GetStream()) 
     { 
      string msg = new BinaryReader(n).ReadString(); 
      if (msg == "exit") 
       // Client told us to exit... 
       shouldExit = true; 
      BinaryWriter w = new BinaryWriter(n); 
      w.Write(msg + " back atcha!"); 
      w.Flush(); // Must call Flush because we're not disposing the writer. 
     } 
    } 

這是所有在文檔中的例子:http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx

+1

這裏不需要調用'Close()' - 它在'using'語句中,所以它被自動處理。循環是問題。 – 2012-01-06 17:25:52

+0

是的,你是對的(當然) – 2012-01-06 17:27:09

3

看評論在您的服務器代碼的開始

static void Server()  // Handles a single client request, then exits. 

完全正確 - 您只需撥打AcceptTcpClient一次,然後迴應,然後關閉聽衆。這將只處理一個連接。如果您希望它處理多個連接,則需要循環 - 很可能在循環和再次接受之前將每個TCP客戶端交給單獨的線程。

2

您在Server()方法評論回答自己的問題:

// Handles a single client request, then exits. 

在你讀完第一個字符串,你叫listener.Stop(),然後從函數返回,因此線程退出。如果你希望服務器爲後續請求保持活動,你將不得不包含某種循環。

2

在您的服務器上,您在收到第一條消息後處置客戶端。

如果要保持TCP連接處於活動狀態,則需要將TCP客戶端保存在服務器方法中。然後你可以使用像client.GetStream().Read()這樣的方法來讀取客戶端的數據。請注意,此方法將阻塞,直到您收到來自流的消息。

爲了處理N個請求,你將不得不做一些類型的循環:

while(true) { 
    string msg = client.GetStream().Read(); 
    // do something with the message 
} 

也有異步方法,這將讓你在另一個線程上執行這些操作。查看流上的BeginRead()方法。