[英]Sending some constraints to client from server in C#
我使用C#中的套接字编程创建了一个简单的服务器,它将从客户端接收文件。 我的示例代码段如下。
我想添加一些限制。 我想限制文件大小(例如4 KB或2 KB)和允许的文件格式(例如.doc,.txt,.cpp等)的限制,这些文件格式会在客户端尽快发送给客户端连接到服务器,以便客户端可以相应地发送文件。 我该怎么做?
示例代码段:
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...
}
}
}
}
我必须在代码中添加哪些其他行才能将限制发送给客户端?
基本上我认为您主要需要两件事:
定义其他答案中建议的应用程序协议
并处理部分读/写
为了处理部分读取(不确定要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;
}
}
传统的Stream.Read()
不能保证读取您所告知的字节数,另一方面,此方法将确保读取的字节数与data.Length
参数中指定的字节数相同。 因此,您可以使用此类功能来实现所需的应用程序协议。
您也可以在此处找到有关此类应用程序协议的一些相关信息
好的,例如,这是服务器如何发送文件长度限制和文件扩展名:
// 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
但是您仍然需要某种协议,否则您应该让客户端读取“完整”流并在以后以某种方式解析这些数据,如果数据没有固定长度等,则这并非易事-否则客户端将如何区分哪个消息的一部分是文本,哪个整数?
您似乎在犯经典套接字错误。 给定的代码和解释似乎假定套接字在消息中处理。 他们没有 。 以这种方式使用时,您正在使用流式Internet套接字 ,该套接字提供流而不是message 。
您没有显示执行实际发送的任何代码,因此我猜测您只是将文件数据泵送到另一端并关闭了连接。 您还怎么知道您已经成功传输了整个文件?
客户端和服务器为了通过套接字有效地交换数据而必须遵循的这套规则称为应用程序协议 。 您将必须拥有一个,否则您将只向$ deity发送数据就知道在哪里,而且您将完全无法控制它。 这意味着服务器或客户端都不会知道发生了什么,他们只是在发送和接收数据,并希望一切顺利。 因此,您不必在代码中添加“几行”,而必须完全对其进行重组。
定义应用程序协议的方法有很多,可以选择的选项很多,因此,我将向您展示一个任意的协议:对消息的文本说明,该消息以ID和有效载荷长度(如果适用)为前缀未指定的数字变量。 例如,您可以选择little-endian四字节无符号整数。
这种格式的消息称为“类型/长度/值”或TLV 。 因此,我们定义了以下消息:
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.
现在,所需要做的就是在服务器和客户端中实施此应用程序协议,您已完成。
您还必须决定如果客户端或服务器不遵守协议该怎么办。 例如,它可以发送您无法解析的消息,未知的消息ID,您不希望支持的消息长度,乱序消息(IncomingFile之前的FileUpload)或不是符合较早发送的消息,例如客户端上传的文件大于服务器认为可以接受的文件或扩展名无效。 您还必须考虑“确认”或响应消息,例如服务器告诉客户端“确定,继续,发送下一条消息”。
总而言之,这是一个非常广泛的问题,并不容易回答。 我在对您的问题的评论中试图解决此问题,该问题已被删除。 因此,在这里您有答案。
您可以在网上了解更多有关此的信息,例如Giorgi链接的Beej的《网络编程指南》 (一定要阅读整个指南)和Stephen Cleary的博客 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.