繁体   English   中英

C#TCP套接字连接用意外字符替换了返回数据

[英]C# TCP socket connection replacing return data with unintended characters

我正在服务器-客户端身份验证系统上进行实验,我的目标是向TCP服务器发送一些详细信息,例如mac id,ip地址等,然后服务器将其接收,检查数据库是否存在指定的地址,如果存在,它将返回“ 0”作为返回数据。 客户端然后读取它并启动OnAuthorized函数。

所以,问题是,客户端发送数据,服务器读取它,然后返回0,但是在代码上,我看到了

0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\

而不是在控制台上显示为“ 0”,但下一行很低,因此我假设其空白字符,但Trim()应该将其删除吗? 但是没有。 我正在使用断点,并在HTML Visualizer中检查了返回值,并看到了单个字符0,但它并未反映在实际的字符串上。 这是代码。

客户

IPEndPoint IPEndPoint = new IPEndPoint(ServerIP, Constants.SecurityServerPort);
            Client.Connect(IPEndPoint);
            Logger.LogGenericInfo("Socket created to {0}", Client.RemoteEndPoint.ToString());
            byte[] sendmsg = Encoding.ASCII.GetBytes(MsgToSend);
            int Send = Client.Send(sendmsg);
            int Received = Client.Receive(Data);

            if(Data != null)
            {
                ReceivedData = Encoding.ASCII.GetString(Data).Trim(' ');
                Logger.LogGenericInfo(ReceivedData);
            }

            Client.Shutdown(SocketShutdown.Both);
            Client.Close();

服务器:

IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 7205);
        ConsoleKeyInfo key;
        int count = 0;
        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sock.Bind(localEndpoint);
        sock.Listen(5);
        while (true)
        {

            Console.WriteLine("\nWaiting for clients..{0}", count);
            Socket confd = sock.Accept();
            int b = confd.Receive(Buffer);
            data += Encoding.ASCII.GetString(Buffer, 0, b);
            Console.WriteLine("" + data);
            data = null;
            confd.Send(Message);
            Console.WriteLine("\n<< Continue 'y' , Exit 'e'>>");
            key = Console.ReadKey();
            if (key.KeyChar == 'e')
            {
                Console.WriteLine("\nExiting..Handled {0} clients", count);
                confd.Close();
                System.Threading.Thread.Sleep(5000);
                break;
            }
            confd.Close();
            count++;
        }

服务器返回数据= private static byte[] Message = Encoding.ASCII.GetBytes("0");

客户端将数据接收到其缓冲区中,但是您不使用存储的接收多少字节的值:

        int Received = Client.Receive(Data);

然后,您将整个缓冲区变成一个字符串,其中将包含许多NUL字符(ascii 0)以及您的零字符数字(ascii 48)。 如果重新使用该缓冲区,这也会重复使用旧数据,并可能带来安全风险:

        if(Data != null)
        {
            ReceivedData = Encoding.ASCII.GetString(Data).Trim(' ');

顺便说一句, if这将永远是正确的。 也许你的意思是if(Received > 0)

然后,您尝试使用trim修剪掉这些,但是您告诉c#修剪掉空格(ascii 32),它不是一个污染的空间,它是一个NUL(ascii 0)。

您最好在服务器端执行操作,并使用Received of bytes限制GetString返回的字符数。 这是您在服务器端执行的操作:

        int b = confd.Receive(Buffer);
        data += Encoding.ASCII.GetString(Buffer, 0, b);

您在服务器上使用b。 在客户端上,您不使用Received。 我不太确定为什么要说data +=因为这会将您当前的数据添加到以前的数据中,但这也许是故意的

顺便说一句,请避免命名方法范围的变量(在方法主体中定义的变量,例如int Received ,开头是大写字母。在c#中,此约定适用于可公开访问的属性,方法,事件,类级变量等。不遵循这些约定的代码很难读取,因为这些变量未在其名称暗示它们将被定义的位置定义

您可能还会遇到此代码的问题,因为服务器只会响应一次客户端,然后在等待来自您的控制台输入时暂停。 同样,这可能是有意的,但似乎不太可能。 我建议您切换到使用异步样式编程来在服务器端接收和处理数据,然后服务器将能够同时为多个客户端提供服务。 现在,即使您删除控制台交互,也将很难做到这一点。 尽管您可能希望此服务器非常简单,但是对于“读取某些数据,执行某些工作,写入某些数据”这种“同步”的方式,这并不是“如何完成服务器”的理想介绍,因为第一个客户端具有等待工作完成,第二个客户端必须等到第一个客户端离开。

最后一点(承诺)-c#内置了几种方法(例如微服务体系结构实现),其中所有这些低级支持,将字节写入套接字等,它被我们夺走了,Microsoft确实做得很好,而我们所要做的就是要做的就是定义一个服务,并指定操作的名称(通过编写名为thatthing的方法)并编写实现该操作的服务器端代码。然后在客户端,我们基本上告诉Visual Studio“我要使用该服务”,它会编写将其链接所需的所有客户端代码,因此,客户端基本上可以分为两行(创建客户端,调用方法),在这种情况下,服务器端大约为三行(声明方法,读取值,返回响应值),它的多线程异步功能完美运行,不会造成混乱的字节和编码,套接字操作,循环等等

按照此处的操作方式进行操作,非常适合学习和欣赏底层工作原理,但这有点像编写自己的显示驱动程序,而不是使用Nvidia的显示驱动程序。 没有太多的意义

一个简单的hello world示例(与您所做的操作大致相同): https : //docs.microsoft.com/zh-cn/dotnet/framework/wcf/feature-details/how-to-create-a-basic -wcf-web-http-service

有关servicehost的更多详细信息: https ://docs.microsoft.com/zh-cn/dotnet/framework/wcf/hosting-services

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM