[英]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.