Как я могу подключиться к серверу TCP с помощью веб-браузера?

N.B. Те, кто комментирует этот вопрос, очень широкий (также отрицательное и закрывающее): вам не нужно сосредотачиваться на деталях. Единственная проблема - использовать браузер.


Предыстория проблемы:

У меня есть следующие требования: у меня есть клиент (myClient.exe) и один сервер (myServer.exe), который прослушивает порт №43.

Клиент может отправлять на сервер команды GET / PUT / POST в стиле WHOIS и HTTP (0.9, 1.0 и 1.1), и сервер должен понимать и реагировать на любой стиль команды.

Пользователи также должны иметь возможность подключаться к серверу с помощью веб-браузеров.


Что у меня в руке:

Я уже реализовал правила WHOIS и HTTP. Единственная проблема, с которой я столкнулся, это то, что я не могу подключиться к серверу с помощью обычного интернет-браузера.

Сервер работает по адресу localhost:5000. Я попытался подключиться к серверу с помощью Internet-Explorer, и мне это не удалось. Браузер продолжает попытки и в конечном итоге показывает страницу сбоя.

введите здесь описание изображения

Что мне сейчас нужно:

Мне нужно предложение, чтобы я мог изменить свой код для подключения моего браузера к myServer.exe.


Исходный код:

Исходный код для ClientClass находится здесь.

Сервер

class ServerProgram
{
    static Dictionary<string, string> NameLocationDictionary;
    static Dictionary<string, ClientClass> ClientDictionary;

    static void Main(string[] args)
    {
        Console.Title = "Server";

        CommandLineParser parser = new CommandLineParser();
        parser.Args = new List<string>(args);
        parser.FlagChar = new List<string>(new string[] {"-"});
        parser.Acquire();

        if (parser.Count > 0)
        {
            //TODO: log file save
            if (parser.ContainsOption("-l"))
            {
                OptionArgsPosition oap = parser.GetArgument("-l");

                if (oap != null)
                {
                    LogFile.Name = oap.Argument;
                    parser.Remove("-l");
                } 
            }

            if (parser.ContainsOption("-f"))
            {
                OptionArgsPosition oap = parser.GetArgument("-f");

                if (oap != null)
                {
                    TextFile txtFile = new TextFile();
                    txtFile.Name = oap.Argument;
                    string text = txtFile.Read();
                    string[] lines = text.Split(new string []{ "\r\n"}, StringSplitOptions.RemoveEmptyEntries);

                    //load to name-location dictionary
                    foreach (string s in lines)
                    {
                        string [] keyValue = s.Split(',');

                        if (NameLocationDictionary == null)
                        {
                            NameLocationDictionary = new Dictionary<string, string>();
                        }

                        NameLocationDictionary.Add(keyValue[0], keyValue[1]);
                    }

                    parser.Remove("-f");
                }
            }
        }

        ClientDictionary = new Dictionary<string, ClientClass>();

        if (NameLocationDictionary == null)
        {
            NameLocationDictionary = new Dictionary<string, string>();                
            NameLocationDictionary.Add("TONY4", "TONY4-location");
            NameLocationDictionary.Add("xyzgy", "xyzgy-location");
            NameLocationDictionary.Add("cssbct", "RB-336");
        }

        if (string.IsNullOrEmpty(LogFile.Name) || string.IsNullOrWhiteSpace(LogFile.Name))
        {
            LogFile.Name = "log.txt";
        }

        string ipAddress = Constants.LOCAL_HOST_IP;
        int portNo = Constants.PORT_NO;

        IPAddress ip = IPAddress.Parse(ipAddress);
        TcpListener listener = new TcpListener(ip, portNo);
        listener.Start();

        Console.WriteLine("Server program started on address [" + Constants.LOCAL_HOST_IP + ":" + Constants.PORT_NO + "]");

        //// poll for TCP clients in a 2nd thread
        Thread incomingClientThread = new Thread(delegate ()
        {
            ServerProgram.PollIncomingClientConns(listener);
        });
        incomingClientThread.Start();
        Console.ReadLine();

    }

    #region catching client connections
    static void PollIncomingClientConns(TcpListener listener)
    {
        try
        {
            bool keepRunning = true;

            while (keepRunning)
            {
                ClientClass client = new ClientClass(listener);

                if (client.IsConnected)
                {
                    Console.WriteLine("Server connected with client [{0}]", client.ID);

                    ClientDictionary.Add(client.ID, client);

                    Thread thread = new Thread(delegate ()
                    {
                        ServerProgram.ReadFromClient(client);
                    });
                    thread.Start();
                }
            }

            throw new Exception();
        }
        catch (Exception ex)
        {
            var inner = ex.InnerException as SocketException;
            if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
                Console.WriteLine("Disconnected in [ServerProgram.Main.catch]");
            else
                Console.WriteLine(ex.Message);

            listener.Stop();
        }
    } 
    #endregion

    static void ReadFromClient(ClientClass client)
    {
       try
        {
            Console.WriteLine("New Thread of [{0}] in [ServerProgram.ReadfromClient", client.ID);

            CommandLineParser parser = new CommandLineParser();
            parser.FlagChar = new List<string>(new string[] {"-"});

            while (client.Tcp.Connected)
            {
                string args = client.Read();
                args = args.Replace('\r', ' ');
                args = args.Replace('\n', ' ');

                Regex r = new Regex("([^\" ][^ ]*)|(\"[^\"]*\")");
                string [] splittedArgs = r.Matches(args).OfType<Match>().Select(m => m.Value).ToArray();

                parser.Args = new List<string>(splittedArgs);
                parser.Acquire();

                if(args.Contains("GET") || args.Contains("PUT") || args.Contains("POST"))
                {
                    List<string> commands = parser.Args;

                    commands[1] = commands[1].TrimStart(new char[] { '/', ' ', '?'});//recover [name]

                    if (!args.Contains("HTTP")) // HTTP 0.9
                    {
                        #region HTTP 0.9
                        if (commands[0] == "GET")//HTTP-0.9 request received
                        {
                            if (NameLocationDictionary.ContainsKey(commands[1]))
                            {
                                string location = NameLocationDictionary[commands[1]];

                                string responseText = Http09Text.GET_name_Response_Success_3(location);
                                client.Write(responseText);                                    
                                client.Disconnect();
                                Console.WriteLine(responseText);

                                LogFile.Write(client.ClienIPAddess, "GET " + commands[1], ActionType.OK);
                            }
                            else
                            {
                                string responseText = Http09Text.GET_PUT_name_Response_Fail_4();
                                client.Write(responseText);
                                client.Disconnect();
                                Console.WriteLine(responseText);

                                LogFile.Write(client.ClienIPAddess, "GET " + commands[1], ActionType.UNKNOWN);
                            }
                        }
                        if (commands[0] == "PUT")
                        {
                            if (NameLocationDictionary.ContainsKey(commands[1]))//update [location]
                            {
                                NameLocationDictionary[commands[1]] = commands[2];
                                string responseText = Http09Text.PUT_name_location_Response_Success_5(commands[2]);
                                client.Write(responseText);
                                client.Disconnect();
                                Console.WriteLine(responseText);

                                LogFile.Write(client.ClienIPAddess, "PUT " + commands[1] + " " + commands[2], ActionType.OK);
                            }
                            else
                            {
                                string responseText = Http09Text.GET_PUT_name_Response_Fail_4();
                                client.Write(responseText);
                                client.Disconnect();
                                Console.WriteLine(responseText);

                                LogFile.Write(client.ClienIPAddess, "PUT " + commands[1] + " " + commands[2], ActionType.UNKNOWN);
                            }
                        }
                        #endregion
                    }
                    else // HTTP 1.0, or, HTTP 1.1 ...
                    {
                        #region HTTP 1.0
                        if (args.Contains(Constants.HTTP10))
                        {
                            if (commands[0] == "GET")//HTTP-1.0 request received
                            {
                                if (NameLocationDictionary.ContainsKey(commands[1]))
                                {
                                    string location = NameLocationDictionary[commands[1]];

                                    string responseText = Http10Text.GET_name_Response_Success_3(location);
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "GET " + commands[1], ActionType.OK);
                                }
                                else
                                {
                                    string responseText = Http10Text.GET_PUT_name_Response_Fail_4();
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "GET " + commands[1], ActionType.UNKNOWN);
                                }
                            }
                            if (commands[0] == "POST")
                            {
                                List<string> comms = commands;

                                string key = comms[1];
                                string location = comms[comms.Count - 1];

                                if (NameLocationDictionary.ContainsKey(key))//update [location]
                                {
                                    NameLocationDictionary[key] = location;
                                    string responseText = Http10Text.PUT_name_location_Response_Success_5();
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "POST " + key + " " + location, ActionType.OK);
                                }
                                else
                                {
                                    string responseText = Http10Text.GET_PUT_name_Response_Fail_4();
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "POST " + key + " " + location, ActionType.UNKNOWN);
                                }
                            }
                        }
                        #endregion
                        #region HTTP 1.1
                        if (args.Contains(Constants.HTTP11))
                        {
                            if (commands[0] == "GET")//HTTP-1.0 request received
                            {
                                string key = commands[1];

                                if (NameLocationDictionary.ContainsKey(key))
                                {
                                    string location = NameLocationDictionary[key];

                                    string responseText = Http11Text.GET_name_Response_Success_3(location);
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "GET " + key, ActionType.OK);
                                }
                                else
                                {
                                    string responseText = Http11Text.GET_POST_name_Response_Fail_4();
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "GET " + key, ActionType.UNKNOWN);
                                }
                            }
                            if (commands[0] == "POST")
                            {
                                string lastLine = commands[commands.Count - 1];
                                string[] keyLocation = lastLine.Split('&');
                                string[] keyKey = keyLocation[0].Split('=');
                                string[] locLoc = keyLocation[1].Split('=');

                                string key = keyKey[1];
                                string location = locLoc[1];

                                if (NameLocationDictionary.ContainsKey(key))//update [location]
                                {
                                    NameLocationDictionary[key] = location;
                                    string responseText = Http11Text.POST_name_location_Response_Success_5();
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "POST " + key + " " + location, ActionType.OK);
                                }
                                else
                                {
                                    string responseText = Http11Text.GET_POST_name_Response_Fail_4();
                                    client.Write(responseText);
                                    client.Disconnect();
                                    Console.WriteLine(responseText);

                                    LogFile.Write(client.ClienIPAddess, "POST " + key + " " + location, ActionType.UNKNOWN);
                                }
                            }
                        } 
                        #endregion
                    }                                        
                }
                else                    
                {
                    #region WHOIS 
                    List<string> comms = parser.Args;

                    int argCount = comms.Count;

                    if (argCount == 1)//return location
                    {
                        string key = comms[0];

                        if (NameLocationDictionary.ContainsKey(key))
                        {
                            string value = NameLocationDictionary[key];
                            string text = key + " is in " + value;
                            client.Write(text);
                            client.Disconnect();
                            Console.WriteLine(text);

                            LogFile.Write(client.ClienIPAddess, "GET " + key, ActionType.OK);
                        }
                        else
                        {
                            client.Write("ERROR: no entries found!");

                            LogFile.Write(client.ClienIPAddess, "GET " + key, ActionType.UNKNOWN);
                        }
                    }
                    if (argCount == 2)
                    {
                        string key = comms[0];
                        string value = comms[1];

                        if (NameLocationDictionary.ContainsKey(key))//update [location]
                        {
                            NameLocationDictionary[key] = value;
                            client.Write(key + " is in " + value);
                            client.Disconnect();
                            Console.WriteLine(key + " is in " + value);

                            LogFile.Write(client.ClienIPAddess, "PUT " + key + " " + value, ActionType.OK);
                        }
                        else
                        {
                            client.Write("ERROR: no entries found!");
                        }
                    }
                    #endregion
                }
            }
        }
        catch(Exception ex)
        {
            client.Disconnect();
            ClientDictionary.Remove(client.ID);
            client.Dispose();
            client = null;

            Console.WriteLine(ex.Message);
        }
    }

    static void ListConnectedClients()
    {
        while (true)
        {
            Console.Write("Command prompt # ");
            string command = Console.ReadLine();
        }
    }
}

Клиент

public class ClientProgram
{
    static string clientID = string.Empty;
    static string otherClientID = string.Empty;
    static string host = string.Empty;
    static int port = -99;

    #region void Start()
    public static void Start(string[] args)
    {
        try
        {
            CommandLineParser parser = new CommandLineParser();
            parser.Args = new List<string>(args);
            parser.FlagChar = new List<string>(new string[] { "-" });
            parser.Acquire();

            host = Constants.LOCAL_HOST_IP;
            port = Constants.PORT_NO;

            if (parser.Options != null)
            {
                if (parser.Options.Contains("-h"))
                {
                    OptionArgsPosition oap = parser.GetArgument("-h");

                    if (oap != null)
                    {
                        if (oap.Argument != null)
                        {
                            host = oap.Argument;
                            parser.Remove("-h");
                        }
                    }
                }
                if (parser.Options.Contains("-p"))
                {
                    OptionArgsPosition oap = parser.GetArgument("-p");

                    if (oap != null)
                    {
                        if (oap.Argument != null)
                        {
                            port = Convert.ToInt32(oap.Argument);
                            parser.Remove("-p");
                        }
                    }
                }
                if (parser.Options.Contains("-h0")
                    || parser.Options.Contains("-h1")
                    || parser.Options.Contains("-h9"))
                {//HTTPClient
                    string name = String.Empty;
                    string location = String.Empty;

                    //Task<string> response = MyHttpClientClass.Getrequest(ip, port.ToString()); 
                    ClientClass client = new ClientClass(host, port);

                    try
                    {
                        Console.Title = "Client " + "[" + client.ID + "]";

                        bool success = client.Connect();

                        if (success)
                        {
                            Console.WriteLine("Client [{0}] is connected.", client.ID);

                            ClientProgram.WriteToHttpServer(client, parser);
                        }
                    }
                    catch (Exception ex)
                    {
                        client.Disconnect();
                        client.Dispose();
                        client = null;

                        Console.WriteLine(ex.Message);
                    }
                }
            }
            else//TCP client
            {
                ClientClass client = new ClientClass(host, port);

                try
                {
                    Console.Title = "Client " + "[" + client.ID + "]";

                    bool success = client.Connect();

                    if (success)
                    {
                        Console.WriteLine("Client [{0}] is connected.", client.ID);

                        ClientProgram.WriteToTcpServer(client, parser);
                    }
                }
                catch (Exception ex)
                {
                    client.Disconnect();
                    client.Dispose();
                    client = null;

                    Console.WriteLine(ex.Message);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private static void WriteToHttpServer(ClientClass client, CommandLineParser parser)
    {
        try
        {
            if (client.Tcp.Connected)
            {
                if (parser.Count < 0)
                {
                    client.Disconnect();
                    Environment.Exit(0);
                }
                else
                {
                    if (parser.Options.Contains("-h9"))
                    {
                        parser.Remove("-h9");

                        if (parser.Count == 1)
                        {
                            OptionArgsPosition oap = parser[0];

                            if (oap != null)
                            {
                                string str = "GET /" + oap.Option + "\r\n";
                                client.Write(str);
                            }
                        }
                        if (parser.Count == 2)
                        {
                            OptionArgsPosition oapName = parser[0];
                            OptionArgsPosition oapLocation = parser[1];

                            if (oapName != null && oapLocation != null)
                            {
                                string str = "PUT /" + oapName.Option + "\r\n\r\n" + oapLocation.Option + "\r\n";
                                client.Write(str);
                            }
                        }
                    }
                    if (parser.Options.Contains("-h0"))
                    {
                        parser.Remove("-h0");

                        if (parser.Count == 1)
                        {
                            OptionArgsPosition oap = parser[0];

                            if (oap != null)
                            {
                                string str = "GET /?" + oap.Option + " HTTP/1.0\r\n<optional header lines>\r\n";
                                client.Write(str);
                            }
                        }
                        if (parser.Count == 2)
                        {
                            OptionArgsPosition oapName = parser[0];
                            OptionArgsPosition oapLocation = parser[1];

                            if (oapName != null && oapLocation != null)
                            {
                                string str = "POST /" + oapName.Option + " HTTP/1.0\r\nContent-Length: 72\r\n<optional header lines>\r\n" + oapLocation.Option;
                                client.Write(str);
                            }
                        }
                    }
                    if (parser.Options.Contains("-h1"))
                    {
                        parser.Remove("-h1");

                        if (parser.Count == 1)
                        {
                            OptionArgsPosition oap = parser[0];

                            if (oap != null)
                            {
                                string str = "GET /?" + oap.Option + " HTTP/1.1\r\nHost: " + host + "\r\n<optional header lines>\r\n";
                                client.Write(str);
                            }
                        }
                        if (parser.Count == 2)
                        {
                            OptionArgsPosition oapName = parser[0];
                            OptionArgsPosition oapLocation = parser[1];

                            if (oapName != null && oapLocation != null)
                            {
                                string str = "POST HTTP/1.1\r\nHost: " + host + "\r\nContent-Length: 72\r\n<optional header lines>\r\nname=" + oapName.Option + "&location=" + oapLocation.Option;
                                client.Write(str);
                            }
                        }
                    }

                    Console.WriteLine(parser[0].Option);
                    Console.WriteLine("From server : " + client.Read());
                }
            }

            Console.WriteLine("ClientProgram.WriteToTcpServer.Done");
        }
        catch (Exception ex)
        {
            client.Disconnect();
            client.Dispose();
            client = null;

            Console.WriteLine(ex.Message);
        }
    }
    #endregion

    #region void WriteToServer()
    private static void WriteToTcpServer(ClientClass client, CommandLineParser commands)
    {
        //...
    }
    #endregion
}

person user366312    schedule 02.03.2020    source источник
comment
Браузеры говорят по протоколу HTTP. Ваш сервер этого не делает. Ваш вопрос не имеет смысла. Вам придется улучшить свой сервер, чтобы он говорил по протоколу HTTP, а это очень сложная задача.   -  person user207421    schedule 10.03.2020
comment
Таким образом, вам необходимо внедрить WHOIS, а также HTTP. Слишком широкий и становится все шире.   -  person user207421    schedule 10.03.2020
comment
Я согласен, что это очень широко, и я не уверен, является ли прослушивание TCP-порта хорошей идеей для этого или нет без дополнительного контекста. Вы можете изучить WebSockets, чтобы узнать, полезен ли он для вас: html5rocks.com/ ru / tutorials / websockets / basics   -  person Alex KeySmith    schedule 10.03.2020
comment
В вашем вопросе нет свидетельств того, что вы уже реализовали протокол HTTP или WHOIS, поэтому вы не можете рационально удивляться, что об этом никто не знает. И очевидно, что вы сделали это неправильно, иначе ваш браузер работал бы. Итак, вам нужно опубликовать фактический код. И фактическое сообщение об ошибке или ответ, а не просто повторение «не могу подключиться к серверу с помощью обычного интернет-браузера» и «мне не удалось». Ваш вопрос не является полным и не подлежит ответу в его нынешней форме.   -  person user207421    schedule 10.03.2020
comment
Вздох. Это один ответ на три вопроса. Что вам показал браузер и что вы ему отправили?   -  person user207421    schedule 10.03.2020
comment
Двойной вздох. 1. Вы до сих пор не сообщили нам, что отображает браузер. 2. Вам необходимо отправить клиенту HTTP с HTML в теле. Вы все еще даже не начинаете предоставлять достаточно информации. Я не прошу описания того, что вы отправляете. Я спрашиваю что вы отправили и ожидаю, что вы отредактируете весь переданный ответ в свой вопрос. 3. Что касается того, что вы подразумеваете под «идентификатором клиента», «идентификатором браузера» или «механизмом идентификации», или почему вы думаете, что они вам нужны, я понятия не имею.   -  person user207421    schedule 10.03.2020
comment
Ваш ответ HTTP неверен. См. RFC 2616 и последующие. Слишком широкий.   -  person user207421    schedule 10.03.2020
comment
Не удаляйте свой код. Здесь, в вопросе, должен быть указан код, являющийся частью вопроса. Не по ссылке.   -  person user207421    schedule 11.03.2020
comment
Из Google, который тоже выглядит как код C # - хотите также пометить вопрос этим?   -  person JGFMK    schedule 16.03.2020


Ответы (1)


Простой HTTP-совместимый сервер всего на несколько шагов опережает сервер двоичных сокетов. Вы уже пишете ответ клиенту. Если первая строка ответа соответствует стандарту HTTP, браузер сможет отобразить ее.

Для иллюстрации вот несколько строк кода из одного из моих недавних проектов.

var message = new StringBuilder();
message.Append("HTTP/1.1 200 OK\n\n");
var length = message.Length;
var outgoingBuffer = new ArraySegment<byte>(Encoding.ASCII.GetBytes(message.ToString()));
_client.Close();

MDN поддерживает подробную документацию по структуре сообщений HTTP-запросов и ответов по адресу https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages.

person Pranav Negandhi    schedule 15.03.2020