2015-09-27 11 views
6

Tôi đã tạo một máy chủ đơn giản bằng cách sử dụng lập trình socket trong C# sẽ nhận tệp từ phía máy khách. Phân đoạn mã mẫu của tôi được đưa ra dưới đây.Gửi một số ràng buộc cho khách hàng từ máy chủ trong C#

Tôi muốn thêm một số hạn chế. Tôi muốn giới hạn kích thước tệp (chẳng hạn như 4   KB hoặc 2   KB) và các định dạng tệp cho phép (chẳng hạn như .doc, .txt, .cpp, v.v.) sẽ được gửi cho khách hàng ngay sau khi máy khách kết nối với máy chủ sao cho máy khách có thể gửi các tập tin cho phù hợp. Làm thế nào tôi sẽ làm điều đó? đoạn mã

mẫu:

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... 

      } 
     } 
    } 
} 

Những dòng bổ sung, tôi sẽ phải thêm vào đoạn code để gửi các hạn chế cho khách hàng?

+1

Để giới hạn kích thước tệp, chỉ cần thêm bộ đếm kích thước dữ liệu, như "int counter = 0; counter + = recv;". Sau đó, nếu giới hạn vượt quá thả khách hàng với thông điệp thích hợp. –

+0

Tôi chỉ muốn gửi kích thước tệp và định dạng tệp được phép cho khách hàng dưới dạng sson khi khách hàng kết nối để khách hàng có thể gửi tệp cho phù hợp @Alek Depler –

+0

Hm, sau đó bạn phải tạo giao thức máy khách-máy chủ của riêng mình. Cả khách hàng và máy chủ đều có thể gửi dữ liệu cho nhau, bạn cần chia nhỏ tất cả dữ liệu theo hai loại: hướng dẫn giao thức kỹ thuật và chính dữ liệu. Câu trả lời của "CodeCaster" là chính xác –

Trả lời

3

Dường như bạn đang mắc phải lỗi ổ cắm cổ điển. Mã và giải thích đã cho dường như giả định các socket xử lý trong các thông điệp. Chúng không. Khi sử dụng theo cách này, bạn đang sử dụng streaming internet sockets, cung cấp luồng , chứ không phải thông báo.

Bạn không hiển thị bất kỳ mã nào thực sự gửi, vì vậy tôi đoán rằng bạn chỉ cần bơm dữ liệu của tệp sang phía bên kia và đóng kết nối. Làm cách nào khác bạn biết bạn đã chuyển thành công toàn bộ tệp?

Bộ quy tắc này mà máy khách và máy chủ phải tuân thủ để trao đổi dữ liệu thông qua ổ cắm được gọi là application protocol một cách hữu ích. Bạn sẽ phải có, nếu không bạn sẽ chỉ gửi dữ liệu đến vị thần $ biết ở đâu và bạn sẽ không thể kiểm soát được nó. Điều này có nghĩa là máy chủ và khách hàng sẽ không biết điều gì đang xảy ra, họ sẽ chỉ gửi và nhận dữ liệu và hy vọng mọi thứ diễn ra suôn sẻ. Vì vậy, không có "một vài dòng" bạn phải thêm vào mã của bạn, bạn sẽ phải cơ cấu lại nó hoàn toàn. Có rất nhiều cách để xác định một giao thức ứng dụng và nhiều tùy chọn để lựa chọn, vì vậy tôi sẽ chỉ cho bạn một tùy chọn: một lời giải thích văn bản của các thư được bắt đầu bằng ID và độ dài tải trọng (nếu áp dụng), cả trong các biến số không xác định. Bạn có thể chọn số nguyên không dấu bốn byte nhỏ, chẳng hạn.

Thư có định dạng này được gọi là "Type/Length/Value" or TLV. Vì vậy, chúng tôi xác định những thông điệp:

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. 

Bây giờ tất cả những gì cần thiết là thực hiện giao thức ứng dụng này trong máy chủ và máy khách và bạn đã hoàn tất.

Bạn cũng phải quyết định phải làm gì nếu máy khách hoặc máy chủ không tuân thủ prototol. Ví dụ: có thể gửi thư mà bạn không thể phân tích cú pháp, ID tin nhắn không xác định, độ dài tin nhắn mà bạn không muốn hỗ trợ, thông báo không theo thứ tự (FileUpload before IncomingFile) hoặc tin nhắn không phải là phù hợp với các thông điệp được gửi trước đó, như một khách hàng tải lên một tệp lớn hơn máy chủ cho biết nó sẽ chấp nhận hoặc một phần mở rộng không hợp lệ. Bạn cũng phải suy nghĩ về "xác nhận" hoặc tin nhắn phản hồi, như máy chủ nói với khách hàng "OK, tiếp tục, gửi tin nhắn tiếp theo".

Tất cả trong tất cả, đây là rất câu hỏi rộng và không được trả lời dễ dàng. Tôi đã cố giải quyết điều đó trong nhận xét của tôi cho câu hỏi của bạn, câu hỏi đã bị xóa. Vì vậy, ở đây bạn có câu trả lời của bạn.

Bạn có thể tìm hiểu thêm về điều này trên web, ví dụ: Beej's Guide to Network Programming được liên kết với Giorgi (hãy nhớ đọc toàn bộ hướng dẫn) và Stephen Cleary's blog.

4

Về cơ bản tôi nghĩ chủ yếu là bạn cần hai điều:

  • xác định giao thức ứng dụng như đề xuất trong câu trả lời khác

  • và xử lý một phần đọc/viết

Đối xử lý một phần đọc (không chắc chắn cần bao nhiêu chức năng như vậy cho write) bạn có thể sử dụng chức năng như below:

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 là truyền thống Stream.Read() không đảm bảo để đọc như nhiều byte như bạn nói với nó, phương pháp này, mặt khác, sẽ đảm bảo rằng đã đọc càng nhiều byte theo quy định tại data.Length tham số. Vì vậy, bạn có thể sử dụng chức năng như vậy để thực hiện giao thức ứng dụng mong muốn thay thế.

Một số thông tin liên quan về các giao thức ứng dụng như vậy, bạn sẽ tìm thấy here quá


Ok đây là ví dụ cách máy chủ có thể gửi cho giới hạn độ dài file và phần mở rộng tập tin:

// 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 

Nhưng bạn vẫn sẽ cần một số loại giao thức nếu không bạn nên để cho khách hàng đọc dòng "đầy đủ" và phân tích các dữ liệu này sau đó bằng cách nào đó, mà không phải là tầm thường nếu dữ liệu không có độ dài cố định vv - nếu không thì khách hàng sẽ phân biệt phần nào của thông điệp là văn bản, số nguyên nào?

+0

Có một upvote để liên kết với hướng dẫn của Beej. Bất cứ ai thậm chí từ xa quan tâm đến lập trình mạng nên đã đọc hướng dẫn đó ít nhất một lần. – CodeCaster

+0

@CodeCaster: Vâng, thực sự, cảm ơn. Hướng dẫn đó chứa thông tin hữu ích. OP sẽ cần phải xử lý một phần gửi/nhận, và suy nghĩ của một số giao thức, như bạn đề nghị, hoặc TLV, vv –

+0

Giao thức tôi đề nghị _is_ TLV, AFAIK. :-) – CodeCaster

Các vấn đề liên quan