2011-12-10 26 views
6

Tôi đang sử dụng System.Net.SocketsSocket lớp để nhận các gói dữ liệu UDP. Tôi muốn biết chiều dài chính xác của datagram nhận được để kiểm tra tính hợp lệ của datagram.kích thước của gói dữ liệu xếp hàng tiếp theo - UDP

Socket.Receive(Byte()) phương pháp tài liệu nói:

Nếu bạn đang sử dụng một Socket kết nối, Nhận sẽ đọc đầu tiên xếp hàng đợi gói tin từ địa chỉ đích bạn chỉ định trong phương pháp Connect. Nếu datagram bạn nhận được lớn hơn kích thước của tham số đệm, bộ đệm sẽ được lấp đầy với phần đầu tiên của thông báo, dữ liệu dư thừa bị mất và một SocketException được ném ra.

Socket.Available thuộc tính cung cấp tổng số byte có sẵn để đọc, Điều này được tính tổng kích thước của tất cả các gói dữ liệu được xếp hàng đợi.

Có cách nào tôi có thể tìm ra kích thước của datagram tiếp theo không?

public static void Receive() 
{ 
    Byte[] buf, discardbuf; 
    const int paklen = 32;     //correct packet length 
    int l; 

    buf = new Byte[paklen]; 
    discardbuf = new Byte[4096]; 

    while (rcv_enable) 
    { 
     l = soc.Available; 
     if (l == 0) continue; 
     if (l == paklen) soc.Receive(buf); //receive the correct packet 
     else soc.Receive(discardbuf);  //discard otherwise 
     Thread.Sleep(200); 
     Console.WriteLine("Received {0}", l); 
    }; 
} 

Trả lời

3

Tôi sẽ giả định rằng bạn đã phát triển giao thức của riêng bạn và đang mong đợi các gói dữ liệu có kích thước đã biết trước và bạn muốn bảo vệ mình trước các gói lừa đảo.

Kể từ khi thực hiện dường như là một vấn đề và bạn muốn tránh trường hợp ngoại lệ tôi muốn có một cái nhìn tại các overload of Receive mà trả về lỗi socket thô thay vì ném ngoại lệ. Các tài liệu MSDN nào (không chính xác?) Nhà nước rằng phương pháp này cũng sẽ ném một ngoại lệ nhưng tôi không nghĩ rằng đó là trường hợp. Nó chắc chắn là giá trị một thử.

SocketError error; 
byte[] buffer = new byte[512]; // Custom protocol max/fixed message size 
int c = this.Receive(buffer, 0, buffer.Length, SocketFlags.None, out error); 

if (error != SocketError.Success) 
{ 
    if(error == SocketError.MessageSize) 
    { 
     // The message was to large to fit in our buffer 
    } 
} 

Sử dụng một bộ đệm có kích thước lành mạnh trước khi được biết đến và sử dụng quá tải để kiểm tra mã lỗi SocketError nhằm xác định có hay không đọc thành công hoặc nếu bạn sholud thả các gói.

Nếu giao thức của riêng bạn có thể gửi datagram có kích thước không xác định đến giới hạn kích thước datagram tối đa, bạn không có lựa chọn nào khác ngoài việc cấp phát bộ đệm đủ lớn để phù hợp với gói lớn nhất (65k) để tránh các vấn đề về bộ nhớ tùy thuộc vào mã của bạn).

Ngoài ra, hãy xem SocketFlags enum, nó chứa một số thành viên mà bạn có thể quan tâm, chẳng hạn như thành viên Partial và Peek.

+0

Hoàn hảo! Quá tải này thực hiện công việc và không có ngoại lệ nào bị ném. Dường như, Tài liệu MSDN không chính xác. Cảm ơn.-BTW Tôi không thể tìm thấy bất kỳ ví dụ có liên quan cho [SocketFlags enum] (http://msdn.microsoft.com/en-us/library/system.net.sockets.socketflags.aspx) trong MSDN. – Anniffer

+0

@Anniffer tuyệt vời, vui lòng chấp nhận câu trả lời này nếu câu trả lời của bạn được giải đáp :) –

+0

Đã chấp nhận ..... :) – Anniffer

2

Tại sao không chỉ kiểm tra giá trị trả lại từ Receive? im khá chắc chắn mỗi cuộc gọi sẽ trả về một gói dữ liệu.

+0

Nó sẽ hoạt động, nhưng tôi luôn cần phải đọc dữ liệu vào bộ đệm lớn hơn. Nếu không, nếu bộ đệm nhỏ hơn kích thước datagram, Receive() ném ngoại lệ ** Mã lỗi: 10040 ** _Thông báo được gửi trên ổ đĩa datagram lớn hơn bộ đệm thông báo nội bộ hoặc một số giới hạn mạng khác hoặc bộ đệm được sử dụng để nhận một gói dữ liệu vào nhỏ hơn chính datagram - đây thực sự là một mã hiệu năng cao, ngoại lệ quá đắt để ném và xử lý – Anniffer

+0

Ah ok, rất tiếc là không có chuyên gia .NET nhưng một giải pháp có thể tìm ra MTU tối đa của tất cả các giao diện bạn sẽ nhận được gói dữ liệu. Một giải pháp khác là mã hóa bộ đệm thành 65535 byte vì đó là kích thước tối đa UDP datagram (trường độ dài 16 bit), tối đa thực tế thực tế là nhỏ hơn một chút, 65535 - IP-header - UDP-header. –

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