套接字编程c#/客户端 - 服务器通信

时间:2015-11-26 16:00:21

标签: c# sockets iis networking server

我正在尝试在.NET中制作2个程序(在控制台应用程序中),它们通过网络进行通信(代码来自您可以在下面找到的视频,我只是想在调整之前使代码工作) 。请原谅我,我不是一位经验丰富的程序员。

我有一台服务器和一台客户端,当我在我的计算机上(本地)运行它们时,它们可以正常工作。 我可以将多个客户端连接到服务器,发送请求并获得响应。 我在计算机上运行服务器而在另一台计算机上运行客户端时遇到问题,我尝试通过互联网连接。

我可以连接到服务器,但通信不起作用,尝试请求时间时没有数据交换作为示例。我认为问题主要来自网络本身而不是代码。

这是服务器的代码:

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");
    }

&#34; IPADDR&#34;是路由器公共IP的占位符。

这是我当前代码所基于的视频:https://www.youtube.com/watch?v=xgLRe7QV6QI

我直接从中获取了代码(您可以在描述中链接的网站上找到2个代码文件)。

我运行服务器,等待连接。然后我运行尝试连接到服务器的客户端。我连接并在服务器上显示成功的连接。然后客户端发送一个请求,例如&#34; get time&#34;并且服务器应该捕获并响应:

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

返回网络端:

这是我尝试的所有事情的列表,这是在寻找大约一整天的解决方案后问题的常见主要原因:

  • 我已经拥有路由器的静态公共IP(因此公共IP永远不会改变)。尽管如此,我还是在noip.com上创建了动态dns。

  • 我给服务器运行的计算机提供了一个静态租约,因此它始终具有相同的本地IP。

  • 我在Windows防火墙中创建了规则,以确保打开我使用的端口。我在试图通信的两台计算机上都这样做了。

  • 我转发了路由器上的端口,因此它指向服务器运行的计算机的本地IP。 (我尝试了很多不同的端口,没有机会)

  • 我尝试激活&#34; DMZ&#34;在路由器上,但​​它很可能不是解决方案

  • 我尝试创建一个ASP.NET网站,该网页返回一个字符串,使用IIS 7.5发布并进行设置。适用于localhost,但使用公共IP,如&#34; xx.xxx.xxx.xx:PORT / default / index&#34;我收到一个错误。但它显示错误中的网站名称。此外,当使用计算机的本地IP时,它也不起作用(类似于192.168.1.180)。

谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

我了解了消息框架,谢谢CodeCaster。

对于那些对此感到好奇的人,我发现这是一个有趣的链接:http://blog.stephencleary.com/2009/04/message-framing.html

但是在尝试更改代码之前,我在AWS vps上运行服务器并且它立即运行,问题可能来自我的isp或我的路由器。我只是想知道如何在不处理消息框架的情况下工作。