2012-09-06 50 views
8

Tôi chưa bao giờ sử dụng UDP trước đây, vì vậy tôi đã cho nó một đi. Để xem điều gì sẽ xảy ra, tôi đã có 'máy chủ' gửi dữ liệu mỗi nửa giây và máy khách sẽ nhận dữ liệu sau mỗi 3 giây. Vì vậy, ngay cả khi máy chủ đang gửi dữ liệu nhanh hơn nhiều so với máy khách có thể nhận được, khách hàng vẫn nhận được tất cả gọn gàng từng cái một.Dữ liệu được gửi bởi UDP được lưu ở đâu?

Mọi người có thể giải thích lý do tại sao/điều này xảy ra như thế nào? Dữ liệu được đệm chính xác ở đâu?

Gửi

class CSimpleSend 
{ 
    CSomeObjServer obj = new CSomeObjServer(); 

    public CSimpleSend() 
    { 
     obj.changedVar = varUpdated; 
     obj.threadedChangeSomeVar(); 
    } 

    private void varUpdated(int var) 
    { 
     string send = var.ToString(); 
     byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(send); 

     string ip = "127.0.0.1"; 
     int port = 11000; 

     IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port); 
     Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
     client.SendTo(packetData, ep); 

     Console.WriteLine("Sent Message: " + send); 
     Thread.Sleep(100); 
    } 
} 

Tất cả CSomeObjServer không được tăng một số nguyên bởi một mỗi nửa thứ hai

Nhận

class CSimpleReceive 
{ 
    CSomeObjClient obj = new CSomeObjClient(); 

    public Action<string> showMessage; 
    Int32 port = 11000; 
    UdpClient udpClient; 


    public CSimpleReceive() 
    { 
     udpClient = new UdpClient(port); 

     showMessage = Console.WriteLine; 
     Thread t = new Thread(() => ReceiveMessage()); 
     t.Start(); 
    } 

    private void ReceiveMessage() 
    {      
     while (true) 
     { 
      //Thread.Sleep(1000); 
      IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port); 
      byte[] content = udpClient.Receive(ref remoteIPEndPoint); 

      if (content.Length > 0) 
      { 
       string message = Encoding.UTF8.GetString(content); 
       if (showMessage != null) 
        showMessage("Recv:" + message); 

       int var_out = -1; 
       bool succ = Int32.TryParse(message, out var_out); 
       if (succ) 
       { 
        obj.alterSomeVar(var_out); 
        Console.WriteLine("Altered var to :" + var_out); 
       } 
      } 
      Thread.Sleep(3000); 
     } 
    } 
} 

cửa hàng CSomeObjClient biến và có một chức năng (alterSomeVar) để cập nhật nó

Ouput:

Sent Message: 1 
Recv:1 
Altered var to :1 
Sent Message: 2 
Sent Message: 3 
Sent Message: 4 
Sent Message: 5 
Recv:2 
Altered var to :2 
Sent Message: 6 
Sent Message: 7 
Sent Message: 8 
Sent Message: 9 
Sent Message: 10 
Recv:3 
Altered var to :3 
+3

Tôi hoan nghênh bản chất tò mò của bạn, 1 – spender

+1

hệ điều hành có một chồng mà mạng thường có một số bộ đệm ... miễn là những gì bạn gửi phù hợp vào những bộ đệm không có vấn đề ... vì UDP không được đảm bảo anyways dữ liệu có thể được loại bỏ vv – Yahia

+0

Là khách hàng và máy chủ đang chạy trên cùng một máy? – grieve

Trả lời

3

Hạt nhân hệ điều hành duy trì bộ đệm gửi và nhận riêng biệt cho từng ổ cắm UDP và TCP. Nếu bạn google SO_SNDBUFSO_RCVBUF bạn sẽ tìm thấy nhiều thông tin về chúng.

Khi bạn gửi dữ liệu, nó được sao chép từ không gian ứng dụng của bạn vào bộ đệm gửi. Từ đó nó được sao chép vào thẻ giao diện mạng, và sau đó lên dây. Phía nhận là ngược lại: NIC để nhận bộ đệm, nơi nó đợi cho đến khi bạn đọc nó. Ngoài ra các bản sao và đệm cũng có thể xảy ra, tùy thuộc vào hệ điều hành.

Điều quan trọng cần lưu ý là kích thước của các bộ đệm này có thể thay đổi hoàn toàn. Một số hệ thống có thể mặc định ít nhất là 4 kilobyte, trong khi các hệ thống khác cung cấp cho bạn 2 megabyte. Bạn có thể tìm kích thước hiện tại bằng cách sử dụng getsockopt() với SO_SNDBUF hoặc SO_RCVBUF và tương tự đặt nó bằng cách sử dụng setsockopt(). Nhưng nhiều hệ thống giới hạn kích thước của bộ đệm, đôi khi tùy ý số lượng nhỏ. Đây thường là giá trị hạt nhân như net.core.wmem_max hoặc net.core.rmem_max, nhưng tham chiếu chính xác sẽ thay đổi theo hệ thống.

Cũng lưu ý rằng setsockopt() có thể không thành công ngay cả khi bạn yêu cầu số tiền ít hơn giới hạn giả định. Vì vậy, để thực sự có được kích thước mong muốn, bạn cần phải liên tục gọi số setsockopt() bằng cách giảm số tiền cho đến khi thành công.

Các trang sau là một Tech Lưu ý từ công ty của tôi mà chạm về chủ đề này một chút và cung cấp tài liệu tham khảo cho một số hệ thống thông thường: http://www.dataexpedition.com/support/notes/tn0024.html

+0

Câu trả lời hay, cảm ơn! – natli

0

Có vẻ với tôi như UdpClient-Class cung cấp một bộ đệm cho dữ liệu nhận được. Hãy thử sử dụng ổ cắm trực tiếp. Bạn cũng có thể muốn đặt các ổ cắm ReceiveBufferSize về 0, mặc dù tôi tin rằng nó chỉ được sử dụng cho các kết nối TCP.

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