2015-11-26 81 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或我的路由器。我只是想知道如何处理消息帧。

相关问题