草庐IT

C# 客户端/服务器从服务器返回应答给客户端

coder 2023-09-19 原文

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

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

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

服务器.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();
        }
    }
}

最佳答案

您需要将 Response 转换为 byte[],就像您在发送请求的客户端中所做的那样(即 bytesToSend)。例如:

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

就是说,如果没有先阅读有关 TCP 和套接字的引用资料就尝试编写 TCP 代码,您犯了每个人都会犯的典型错误:您错误地认为,当您从套接字读取时,您总是会在每次操作中收到读取的字节。因此,即使使用上述修复(它确实解决了 服务器 端的问题),您也可能会在客户端看到部分响应(在本地测试时不太可能,但如果你转向在 Internet 上或跨 LAN 运行,尤其是随着消息大小的增加)。

对于低容量网络交互,您可能需要考虑使用 StreamReaderStreamWriter 对象包装您的 NetworkStream,并使用 ReadLine()WriteLine() 接收和发送数据(即使用换行符作为数据的分隔符)。

至于处理多个请求,根据您在此处提供的代码,最简单的方法是在 listener.Start() 之后的服务器代码周围添加一个循环> 方法。 IE。包含该语句之后的所有代码,从调用 listener.AcceptTcpClient() 开始,一直到方法中的最后一条语句。然而,这同样只适用于少量网络代码。如果您预计客户端将需要您的服务器处理多个请求,尤其是快速连续的请求,那么您真正想要的是让客户端保持连接,即只连接一次,然后让它在同一个连接上发送多个请求。

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

这样做需要对服务器代码进行重大更改。您确实应该仔细查看 MSDN 和 Stack Overflow 上的各种示例,了解此类事情是如何完成的。我还强烈建议您通读 Winsock Programmer's FAQ .它根本不是专门针对 .NET 的,但确实涵盖了您需要了解的所有关键细节,以便有效且正确地使用 .NET API。

关于C# 客户端/服务器从服务器返回应答给客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37287995/

有关C# 客户端/服务器从服务器返回应答给客户端的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  4. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  7. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  8. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  9. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  10. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

随机推荐