简体   繁体   English

使用C#从服务器向客户端发送一些约束

[英]Sending some constraints to client from server in C#

I have created a simple server using socket programming in C# which will receive a file from the client side. 我使用C#中的套接字编程创建了一个简单的服务器,它将从客户端接收文件。 My sample code segment is given below. 我的示例代码段如下。

I want to add some restrictions. 我想添加一些限制。 I want to make a limit on the file size (such as 4 KB or 2 KB) and allowable file formats (such as .doc, .txt, .cpp, etc.) which will be sent to the client as soon as the client connects to the server so that the client can send files accordingly. 我想限制文件大小(例如4 KB或2 KB)和允许的文件格式(例如.doc,.txt,.cpp等)的限制,这些文件格式会在客户端尽快发送给客户端连接到服务器,以便客户端可以相应地发送文件。 How will I do that? 我该怎么做?

Sample code segment: 示例代码段:

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

namespace FileTransfer
{
    class Program
    {
        static void Main(string[] args)
        {
            // Listen on port 1234

            TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
            tcpListener.Start();

            Console.WriteLine("Server started");

            //Infinite loop to connect to new clients
            while (true)
            {
                // Accept a TcpClient
                TcpClient tcpClient = tcpListener.AcceptTcpClient();
                                Console.WriteLine("Connected to client");
                byte[] data = new byte[1024];
                NetworkStream ns = tcpClient.GetStream();
                int recv = ns.Read(data, 0, data.Length);
                StreamReader reader = new StreamReader(tcpClient.GetStream());

               //Will add some lines to add restrictions...

            }
        }
    }
}

Which additional lines will I have to add to the code to send the restrictions to client? 我必须在代码中添加哪些其他行才能将限制发送给客户端?

Basically I think mainly you need two things: 基本上我认为您主要需要两件事:

  • define application protocol as suggested in other answer 定义其他答案中建议的应用程序协议

  • and handle partial read/writes 并处理部分读/写

For handling partial reads (not sure how much such function is needed for write ) you may use function like below : 为了处理部分读取(不确定要write多少功能),可以使用如下功能:

public static void ReadWholeArray (Stream stream, byte[] data)
{
    int offset=0;
    int remaining = data.Length;
    while (remaining > 0)
    {
        int read = stream.Read(data, offset, remaining);
        if (read <= 0)
            throw new EndOfStreamException 
                (String.Format("End of stream reached with {0} bytes left to read", remaining));
        remaining -= read;
        offset += read;
    }
}

Thing is traditional Stream.Read() doesn't guarantee to read as many bytes as you told it, this method on the other hand, will ensure to have read as many bytes as specified in data.Length parameter. 传统的Stream.Read()不能保证读取您所告知的字节数,另一方面,此方法将确保读取的字节数与data.Length参数中指定的字节数相同。 So you can use such function to implement the desired application protocol instead. 因此,您可以使用此类功能来实现所需的应用程序协议。

Some relevant information about such application protocols you will find here too 您也可以在此处找到有关此类应用程序协议的一些相关信息


Ok this is for example how the server could send file length limit and the file extension: 好的,例如,这是服务器如何发送文件长度限制和文件扩展名:

// Send string
string ext = ".txt";
byte [] textBytes = Encoding.ASCII.GetBytes(ext);
ns.Write(textBytes, 0, textBytes.Length); 

// Now, send integer - the file length limit parameter
int limit = 333;
byte[] intBytes = BitConverter.GetBytes(limit);
ns.Write(intBytes, 0, intBytes.Length); // send integer - mind the endianness

But you will still need some kind of protocol otherwise you should let client read the "full" stream and parse these data later somehow, which isn't trivial if the data doesn't have fixed length etc - otherwise how will the client distinguish which part of the message is text, which integer? 但是您仍然需要某种协议,否则您应该让客户端读取“完整”流并在以后以某种方式解析这些数据,如果数据没有固定长度等,则这并非易事-否则客户端将如何区分哪个消息的一部分是文本,哪个整数?

You seem to be making the classical socket mistake. 您似乎在犯经典套接字错误。 The given code and explanation seem to assume sockets handle in messages. 给定的代码和解释似乎假定套接字在消息中处理。 They don't . 他们没有 When used this way, you're using streaming internet sockets , which provide a stream, not messages . 以这种方式使用时,您正在使用流式Internet套接字 ,该套接字提供流而不是message

You don't show any code that does the actual sending, so I'm guessing that you just pump a file's data to the other side and close the connection. 您没有显示执行实际发送的任何代码,因此我猜测您只是将文件数据泵送到另一端并关闭了连接。 How else will you know you've successfully transferred an entire file? 您还怎么知道您已经成功传输了整个文件?

This set of rules that client and server have to follow in order to usefully exchange data through sockets is called an application protocol . 客户端和服务器为了通过套接字有效地交换数据而必须遵循的这套规则称为应用程序协议 You will have to have one, otherwise you'll just be sending data to $deity knows where, and you'll have no control over it at all. 必须拥有一个,否则您将只向$ deity发送数据就知道在哪里,而且您将完全无法控制它。 This means server nor client will know what's going on, they'll just be sending and receiving data and hoping all goes well. 这意味着服务器或客户端都不会知道发生了什么,他们只是在发送和接收数据,并希望一切顺利。 So there's not "a few lines" you have to add to your code, you'll have to restructure it entirely. 因此,您不必在代码中添加“几行”,而必须完全对其进行重组。

There are many ways to define an application protocol and many options to choose from, so I'm going to show you an arbitrary one: a textual explanation of messages that are prefixed with an ID and a payload length (if applicable), both in unspecified numeric variables. 定义应用程序协议的方法有很多,可以选择的选项很多,因此,我将向您展示一个任意的协议:对消息的文本说明,该消息以ID和有效载荷长度(如果适用)为前缀未指定的数字变量。 You could choose little-endian four-byte unsigned integers, for example. 例如,您可以选择little-endian四字节无符号整数。

Messages in this format are known as "Type/Length/Value" or TLV . 这种格式的消息称为“类型/长度/值”或TLV So we define these messages: 因此,我们定义了以下消息:

ID  Name         Direction         Description                    Payload
1   ServerHello  Server -> Client  The server sends this message  None. 
                                   to every connecting client.    Or maybe server or 
                                                                  protocol version.
2   MaxUpload    Server -> Client  Sent after the ServerHello.    Maximum upload size 
                                                                  in bytes.
3   AllowedExts  Server -> Client  Allowed upload extensions,     The allowed extensions. 
                                   comma-separated. Sent after 
                                   MaxUpload message.
10  IncomingFile Client -> Server  There's a file coming.         The file name.
11  FileUpload   Client -> Server  The file to upload.            The file data.
                                   Sent after IncomingFile.

Now all that's required is to implement this application protocol in server and client and you're done. 现在,所需要做的就是在服务器和客户端中实施此应用程序协议,您已完成。

You also have to decide what to do if a client or server doesn't adhere to the prototol. 您还必须决定如果客户端或服务器不遵守协议该怎么办。 It can for example send a message that you can't parse, an unknown message ID, a message length that you don't want to support, an out-of-order message (FileUpload before IncomingFile) or a message that isn't conform the messages sent earlier, like a client uploading a larger file than the server said it would accept or an invalid extension. 例如,它可以发送您无法解析的消息,未知的消息ID,您不希望支持的消息长度,乱序消息(IncomingFile之前的FileUpload)或不是符合较早发送的消息,例如客户端上传的文件大于服务器认为可以接受的文件或扩展名无效。 You also have to think about "acknowledgement" or response messages, like the server telling the client "OK, go ahead, send the next message". 您还必须考虑“确认”或响应消息,例如服务器告诉客户端“确定,继续,发送下一条消息”。

All in all, this is a very broad question and not answered easily. 总而言之,这是一个非常广泛的问题,并不容易回答。 I tried to address that in my comment to your question, which got removed. 我在对您的问题的评论中试图解决此问题,该问题已被删除。 So here you have your answer. 因此,在这里您有答案。

You can learn more about this on the web, for example Beej's Guide to Network Programming as linked to by Giorgi (be sure to read the entire guide) and Stephen Cleary's blog . 您可以在网上了解更多有关此的信息,例如Giorgi链接的Beej的《网络编程指南》 (一定要阅读整个指南)和Stephen Cleary的博客

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

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