2015-11-26 82 views
0

我想在.NET中通過網絡進行通信(代碼是來自一個視頻,你可以在下面找到,我只是試圖讓2個程序(在控制檯應用程序中)使代碼在適應它之前工作)。原諒我,我不是一個有經驗的程序員。Socket編程c#/客戶端 - 服務器通信

我有一臺服務器和一個客戶端,當我在我的計算機(本地)上運行它們時,它們都能夠完美地工作。 我可以連接多個客戶端到服務器,發送請求並獲得響應。 當我在計算機上運行服務器並在另一臺計算機上運行客戶端時,我遇到了問題,並嘗試通過Internet進行連接。

我可以連接到服務器,但通信不起作用,當試圖請求時間作爲示例時沒有數據交換。我認爲問題主要來自網絡本身而不是代碼。

下面是該服務器的代碼:

class Program 
{ 
    private static Socket _serverSocket; 
    private static readonly List<Socket> _clientSockets = new List<Socket>(); 
    private const int _BUFFER_SIZE = 2048; 
    private const int _PORT = 50114; 
    private static readonly byte[] _buffer = new byte[_BUFFER_SIZE]; 

    static void Main() 
    { 
     Console.Title = "Server"; 
     SetupServer(); 
     Console.ReadLine(); // When we press enter close everything 
     CloseAllSockets(); 
    } 



    private static void SetupServer() 
    { 
     // IPAddress addip = GetBroadcastAddress(); 
     Console.WriteLine("Setting up server..."); 
     _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     _serverSocket.Bind(new IPEndPoint(IPAddress.Any , _PORT)); 
     _serverSocket.Listen(5); 
     _serverSocket.BeginAccept(AcceptCallback, null); 
     Console.WriteLine("Server setup complete"); 
    } 

    /// <summary> 
    /// Close all connected client (we do not need to shutdown the server socket as its connections 
    /// are already closed with the clients) 
    /// </summary> 
    private static void CloseAllSockets() 
    { 
     foreach (Socket socket in _clientSockets) 
     { 
      socket.Shutdown(SocketShutdown.Both); 
      socket.Close(); 
     } 

     _serverSocket.Close(); 
    } 

    private static void AcceptCallback(IAsyncResult AR) 
    { 
     Socket socket; 

     try 
     { 
      socket = _serverSocket.EndAccept(AR); 
     } 
     catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets) 
     { 
      return; 
     } 

     _clientSockets.Add(socket); 
     socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket); 
     Console.WriteLine("Client connected, waiting for request..."); 
     _serverSocket.BeginAccept(AcceptCallback, null); 
    } 

    private static void ReceiveCallback(IAsyncResult AR) 
    { 
     Socket current = (Socket)AR.AsyncState; 
     int received; 

     try 
     { 
      received = current.EndReceive(AR); 
     } 
     catch (SocketException) 
     { 
      Console.WriteLine("Client forcefully disconnected"); 
      current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway 
      _clientSockets.Remove(current); 
      return; 
     } 

     byte[] recBuf = new byte[received]; 
     Array.Copy(_buffer, recBuf, received); 
     string text = Encoding.ASCII.GetString(recBuf); 
     Console.WriteLine("Received Text: " + text); 

     if (text.ToLower() == "get time") // Client requested time 
     { 
      Console.WriteLine("Text is a get time request"); 
      byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString()); 
      current.Send(data); 
      Console.WriteLine("Time sent to client"); 
     } 
     else if (text.ToLower() == "exit") // Client wants to exit gracefully 
     { 
      // Always Shutdown before closing 
      current.Shutdown(SocketShutdown.Both); 
      current.Close(); 
      _clientSockets.Remove(current); 
      Console.WriteLine("Client disconnected"); 
      return; 
     } 
     else 
     { 
      Console.WriteLine("Text is an invalid request"); 
      byte[] data = Encoding.ASCII.GetBytes("Invalid request"); 
      current.Send(data); 
      Console.WriteLine("Warning Sent"); 
     } 

     current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current); 
    } 
} 

在這裏,客戶端代碼:

class Program 
{ 
    private static readonly Socket _clientSocket = new Socket 
     (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

    private const int _PORT = 50114; 

    static void Main() 
    { 
     Console.Title = "Client"; 
     ConnectToServer(); 
     RequestLoop(); 
     Exit(); 
    } 

    private static void ConnectToServer() 
    { 
     int attempts = 0; 

     while (!_clientSocket.Connected) 
     { 
      try 
      { 
       attempts++; 
       Console.WriteLine("Connection attempt " + attempts); 
       _clientSocket.Connect("IpAddr", _PORT); 
      } 
      catch (SocketException) 
      { 
       Console.Clear(); 
      } 
     } 

     Console.Clear(); 
     Console.WriteLine("Connected"); 
    } 

    private static void RequestLoop() 
    { 
     Console.WriteLine(@"<Type ""exit"" to properly disconnect client>"); 

     while (true) 
     { 
      SendRequest(); 
      ReceiveResponse(); 
     } 
    } 

    /// <summary> 
    /// Close socket and exit app 
    /// </summary> 
    private static void Exit() 
    { 
     SendString("exit"); // Tell the server we re exiting 
     _clientSocket.Shutdown(SocketShutdown.Both); 
     _clientSocket.Close(); 
     Environment.Exit(0); 
    } 

    private static void SendRequest() 
    { 
     Console.Write("Send a request: "); 
     string request = Console.ReadLine(); 
     SendString(request); 

     if (request.ToLower() == "exit") 
     { 
      Exit(); 
     } 
    } 

    /// <summary> 
    /// Sends a string to the server with ASCII encoding 
    /// </summary> 
    private static void SendString(string text) 
    { 
     byte[] buffer = Encoding.ASCII.GetBytes(text); 
     _clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None); 
    } 

    private static void ReceiveResponse() 
    { 
     var buffer = new byte[2048]; 
     int received = _clientSocket.Receive(buffer, SocketFlags.None); 
     if (received == 0) return; 
     var data = new byte[received]; 
     Array.Copy(buffer, data, received); 
     string text = Encoding.ASCII.GetString(data); 
     Console.WriteLine(text); 
    } 
} 
static void Main() 
    { 
     Console.Title = "Client"; 
     ConnectToServer(); 
     RequestLoop(); 
     Exit(); 
    } 

    private static void ConnectToServer() 
    { 
     int attempts = 0; 

     while (!_clientSocket.Connected) 
     { 
      try 
      { 
       attempts++; 
       Console.WriteLine("Connection attempt " + attempts); 
       _clientSocket.Connect("IpAddr", _PORT); 
      } 
      catch (SocketException) 
      { 
       Console.Clear(); 
      } 
     } 

     Console.Clear(); 
     Console.WriteLine("Connected"); 
    } 

「IPADDR」 是路由器的公網IP的佔位符。

這是視頻我當前的代碼是基於:https://www.youtube.com/watch?v=xgLRe7QV6QI

我直接把代碼從它(你可以找到在說明鏈接的網站上的2個代碼文件)。

我運行服務器,它等待連接。然後我運行試圖連接到服務器的客戶端。我連接並在服務器上顯示成功的連接。然後,客戶機發出像「獲取時間」的請求,服務器應該抓住它,並作出迴應:

byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString()); 
current.Send(data); 

返回到網絡側:

這是所有我已經試過了事情的清單,這是問題的通常的主要原因尋找一個解決方案約一整天后:

  • 我已經有一個靜態公網IP的路由器(因此公衆IP永遠不會改變)。儘管如此,我在noip.com上創建了一個動態DNS。

  • 我給服務器運行的計算機提供了一個靜態租約,所以它總是有相同的本地ip。

  • 我在Windows防火牆中創建了規則,以確保打開我使用的端口。我在兩臺試圖通信的計算機上都這樣做了。

  • 我轉發了路由器上的端口,以便它指向運行服務器的計算機的本地ip。 (我嘗試了很多不同的端口,沒有機會)

  • 我試過在路由器上啓動「DMZ」,但它是最有可能不是一個解決方案

  • 我試圖創建一個ASP.NET網站,頁面返回一個字符串,使用IIS 7.5發佈並進行設置。在本地主機上工作,但使用公共IP,如「xx.xxx.xxx.xx:PORT/default/index」我收到一個錯誤。但它顯示錯誤中的網站名稱。此外,當使用計算機的本地IP時,它也不起作用(類似於192.168.1.180)。

感謝您的幫助。

+0

不要從YouTube學習代碼,購買一本書。這個例子被打破了,這是浪費時間。它沒有實現協議,所以你的服務器永遠不會收到「獲取時間」,它在一個數據包中收到「get t」,而在另一個數據包中收到「ime」。例如。至少,這是我在快速跳過視頻時看到的。如果您需要幫助調試您的代碼,請在您的問題中包含所有**相關**代碼。 :)連接代碼是無關緊要的,否則你會得到一個你無法連接的異常。錯誤出現在處理數據發送和接收的代碼中。 – CodeCaster

+0

它在本地工作,我不需要任何調試,我花了很多時間在網上找到解決方案,所以我只是在這裏發佈我的問題^^。 –

+1

_「它在我的機器上運行」_是破解網絡代碼的經典借口,但這並不能使它更少受到破壞。如果可以連接,但通信無法按預期工作,則代碼不起作用。我當然不想惹惱你,但是這些教程每天會產生多個這樣的問題。請在您的問題中包含代碼。 – CodeCaster

回答

1

我瞭解了消息框架,謝謝CodeCaster。

的人誰是好奇吧,這裏是一個有趣的鏈接,我發現它:http://blog.stephencleary.com/2009/04/message-framing.html

但試圖改變代碼之前,我跑的AWS VPS服務器和它的工作瞬間,問題可能來自我的isp或我的路由器。我只是想知道如何處理消息幀。

相關問題