C#Client / Server从服务器返回客户端的答案

时间:2016-05-17 23:50:11

标签: c# tcp

我创建了一个简单的客户端/服务器程序,该程序从客户端获取输入并通过查看文本文件返回输入的答案,以查看是否存在与输入相关的答案。

我遇到的问题是我在服务器端获得响应,但我不知道如何将其发送回客户端(它只是返回客户端的输入)。

第二个问题是它会执行一次,因为它只会输入一个输入。我尝试添加一个循环,但无法使其工作。

Server.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;

namespace server
{
    class server
    {
        const string SERVER_IP = "127.0.0.1";
        static void Main(string[] args)
        {
            //Create Dictionary
            Dictionary<string, string> dict = new Dictionary<string, string>();
            //---Read Text File containing commands ---
            StreamReader sr = new StreamReader(@"C:\Users\Desktop\potato.txt");
            string line;

            //Splits the text into commands:responses
            while ((line = sr.ReadLine()) != null)
            {
                string[] arr = line.Split(';');
                dict.Add(arr[0], arr[1]);
            }
            //Print dictionary TESTING FUNCTION
            foreach (KeyValuePair<string, string> kvp in dict)
            {
                Console.WriteLine("Command = {0} Response = {1}", kvp.Key, kvp.Value);
            }

            //---Input the port number for clients to conect---
            Console.Write("Input port" + System.Environment.NewLine);
            int PORT_NO = int.Parse(Console.ReadLine());

            //---listen at the specified IP and port no.---
            IPAddress localAdd = IPAddress.Parse(SERVER_IP);
            TcpListener listener = new TcpListener(localAdd, PORT_NO);
            Console.WriteLine("Listening for Commands");
            listener.Start();

            //---incoming client connected---
            TcpClient client = listener.AcceptTcpClient();

            //---get the incoming data through a network stream---
            NetworkStream nwStream = client.GetStream();
            byte[] buffer = new byte[client.ReceiveBufferSize];

            //---read incoming stream---
            int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);

            //---convert the command data received into a string---
            string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("Received Command : " + dataReceived);

            //---Search Command and send a response
            string Response;
            if (dict.TryGetValue(dataReceived, out Response))
            {
                Console.WriteLine(Response);
            }
            //---write back the response to the client---
            Console.WriteLine("Sending Response : " + Response);
            nwStream.Write(buffer, 0, bytesRead);
            Console.ReadLine();
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您需要将Response转换为byte[],就像发送请求的客户端(即bytesToSend)一样。 E.g:

        Console.WriteLine("Sending Response : " + Response);
        byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(Response);
        nwStream.Write(bytesToSend, 0, bytesToSend.Length);
        Console.ReadLine();

也就是说,如果没有先读取有关TCP和套接字的引用,那么每个人都会尝试编写TCP代码时会犯下经典错误:您错误地认为当您从套接字读取时,您将始终在每个单独的操作中收到已读取的字节。因此,即使使用上述修复(确实解决了服务器方面的问题),您也可能会在客户端看到部分响应(在本地测试时不太可能,但如果您将转移到Internet或跨LAN运行,尤其是当邮件大小增加时。)

对于小批量网络互动,您可能需要考虑将NetworkStreamStreamReaderStreamWriter对象包装在一起,并使用ReadLine()WriteLine()来接收和发送数据(即使用换行符作为数据的分隔符)。

至于处理多个请求,给定您在此处提供的代码,最简单的方法是在 listener.Start()方法之后在服务器代码周围添加一个循环。即包含该语句之后的所有代码,从调用listener.AcceptTcpClient()开始并转到方法中的最后一个语句。但是,这仅适用于低容量网络代码。如果您预计客户端将需要您的服务器来处理多个请求,特别是如果快速连续,您真正想要的是客户端维护连接,即只连接一次然后让它在同一连接上发送多个请求。

同样,如果您希望能够同时处理多个客户端,则无法在单个线程中运行服务器。相反,至少你需要使用你现在正在使用的线程阻塞逻辑,在那里你为每个客户端创建了一个新的线程。更好的方法是使用非阻塞API(例如NetworkStream.BeginRead()StreamReader.ReadLineAsync()等......有许多异步选项可供选择),让.NET为你处理线程。 / p>

这样做需要对服务器代码进行重大更改。你真的应该仔细查看MSDN和Stack Overflow上的各种样本,看看这种事情是如何完成的。我也强烈建议您通读Winsock Programmer's FAQ。它根本不是关于.NET的,而是涵盖了为了有效和正确地使用.NET API而需要了解的所有关键细节。