C#客户端 - 服务器套接字未连接

时间:2018-03-11 23:33:44

标签: c# sockets client-server

我输入了以下视频教程中的C#客户端/服务器课程,...

C# Socket Programming - Multiple Clients

我使用Visual Studio 2017编写了该程序。

该程序没有错误地编译,它可以在SINGLE计算机上运行。也就是说,如果我在同一台计算机上同时运行客户端和服务器,它们就可以正常连接。所以一切似乎都在起作用。

但是,当我尝试将客户端和服务器放在家庭网络上的不同计算机上时,它们将无法连接。当安全防火墙询问时,我允许它们都具有完全访问权限。

我不明白为什么放在通过WiFi连接的同一家庭网络上的不同计算机上时它们不起作用。计算机共享文件没有问题。

此外,根据YouTube上的视频课程,该链接指向已输入的文件。我甚至将它们复制并粘贴到Visual Studio中并编译它们。但我得到了完全相同的结果。他们在一台机器上编译和运行得很好,但我不能让他们在不同的机器上连接。

有什么想法吗?

我无法使用只能连接自己的计算机。

我做错了什么?

以下是硬拷贝客户端代码的链接:

Multi Client

这是一个指向硬拷贝服务器代码的链接:

Multi Server

这是一个非常短的节目。

我不知道我做错了什么。我是否需要添加更多内容才能让它真正识别出自己以外的计算机?

客户代码:

using System;
using System.Net.Sockets;
using System.Net;
using System.Text;

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

    private const int PORT = 100;

    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);
                // Change IPAddress.Loopback to a remote IP to connect to a remote host.
                ClientSocket.Connect(IPAddress.Loopback, 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 program.
    /// </summary>
    private static void Exit()
    {
        SendString("exit"); // Tell the server we are 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);
    }
}
}

服务器代码:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace MultiServer
{
    class Program
    {
        private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private static readonly List<Socket> clientSockets = new List<Socket>();
        private const int BUFFER_SIZE = 2048;
        private const int PORT = 100;
        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()
        {
            Console.WriteLine("Setting up server...");
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
            serverSocket.Listen(0);
            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");
                // Don't shutdown because the socket may be disposed and its disconnected anyway.
                current.Close(); 
                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);
        }
    }
}

注意:我认为代码可能很好。我的问题很可能是权限问题?还是防火墙设置?或者我可能需要指定IP地址?

显然,该程序不会报告任何错误。它不会连接在同一网络上通过WiFi连接的两台笔记本电脑之间。

如果客户端和服务器在同一台计算机上运行,​​它可以正常工作。但这很没用。

1 个答案:

答案 0 :(得分:0)

好的,BEN SEBASTIAN回答了我的问题。

我所要做的就是在客户端软件中指定服务器IP。

ClientSocket.Connect(&#34;指定服务器IP&#34;,PORT);

我以为我昨天已经尝试过了,并且无法让它发挥作用,但今天它没有问题。所以这就是所需要的。

不幸的是,原始视频教程没有详细说明这一点,或者如果他这样做我错过了它。

无论如何,这解决了这个问题。

感谢Ben花时间阅读并回复我的问题。

现在我需要找到一种方法来确保我的服务器笔记本保证始终具有相同的IP地址。我不确定它是由WiFi路由器分配,还是硬盘编码到笔记本中。它可能是动态分配的,所以我可能想要修改它以确保它始终相同。无法使用具有不可靠IP地址的服务器。