2008-09-15 21 views
14

Khi sử dụng Net.Sockets.TcpListener, cách tốt nhất để xử lý các kết nối đến (.AcceptSocket) trong các chuỗi riêng biệt là gì?Làm thế nào để truyền các kết nối đến tcplistener qua các luồng trong .NET?

Ý tưởng là bắt đầu một chuỗi mới khi kết nối mới được chấp nhận, trong khi tcplistener sau đó vẫn có sẵn cho các kết nối đến tiếp theo (và cho mỗi kết nối mới tạo luồng mới). Tất cả các thông tin liên lạc và chấm dứt với khách hàng có nguồn gốc kết nối sẽ được xử lý trong chuỗi.

Ví dụ C# của mã VB.NET được đánh giá cao.

Trả lời

15

Mã mà tôi đã sử dụng trông như sau:

class Server 
{ 
    private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false); 

    public void Start() 
    { 
    TcpListener listener = new TcpListener(IPAddress.Any, 5555); 
    listener.Start(); 

    while(true) 
    { 
     IAsyncResult result = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener); 
     connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event 
     connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request) 
    } 
    } 


    private void HandleAsyncConnection(IAsyncResult result) 
    { 
    TcpListener listener = (TcpListener)result.AsyncState; 
    TcpClient client = listener.EndAcceptTcpClient(result); 
    connectionWaitHandle.Set(); //Inform the main thread this connection is now handled 

    //... Use your TcpClient here 

    client.Close(); 
    } 
} 
+0

Cảm ơn vì mã nguồn, tôi sẽ mã hóa nó như thế này. Chủ đề mới có thể tốn kém, nhưng vì tôi không vượt quá 5 hoặc 6 kết nối đến đồng thời, điều này sẽ ổn cho đến bây giờ. –

+1

Trình nghe suy nghĩ và tcpListener bị nhầm lẫn trong ví dụ, nếu không thì mã tốt. Tìm thấy: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx dựa trên những gì tôi đã đọc ở đây. –

+0

Mã hiện tại rất nguy hiểm trong ngữ cảnh hoạt động, tôi sẽ chỉnh sửa nó ... – Beygi

0

Tôi sẽ sử dụng một threadpool, theo cách này bạn sẽ không phải bắt đầu một chủ đề mới mỗi lần (vì đây là kinda đắt tiền). Tôi cũng sẽ không chờ đợi một cách dứt khoát cho các kết nối furhter, vì khách hàng có thể không đóng kết nối của họ. Làm thế nào để bạn có kế hoạch để định tuyến khách hàng đến cùng một chủ đề mỗi lần?

Rất tiếc, không có mẫu.

3

Tôi tin rằng bạn làm điều đó theo cách tương tự như bất kỳ hoạt động không đồng bộ khác trong .NET: bạn gọi phiên bản BeginXXX của phương pháp này, trong trường hợp này BeginAcceptSocket. Gọi lại của bạn sẽ thực thi trên nhóm luồng.

Chủ đề gộp chung thường tốt hơn nhiều so với kết nối mỗi lần: một khi bạn vượt qua vài chục kết nối, hệ thống hoạt động khó khăn hơn trong việc chuyển đổi giữa các chủ đề hơn là thực hiện công việc thực tế. Ngoài ra, mỗi luồng có ngăn xếp riêng của nó thường có kích thước 1MB (mặc dù nó phụ thuộc vào cờ liên kết) mà phải được tìm thấy trong không gian địa chỉ ảo 2GB (trên các hệ thống 32 bit); trong thực tế điều này giới hạn bạn ít hơn 1000 chủ đề.

Tôi không chắc liệu luồng mạng của .NET hiện có sử dụng nó hay không, nhưng Windows có đối tượng hạt nhân được gọi là Cổng hoàn thành I/O hỗ trợ I/O có thể mở rộng. Bạn có thể kết hợp các chủ đề với đối tượng này và các yêu cầu I/O (bao gồm việc chấp nhận các kết nối đến) có thể được liên kết với nó. Khi một I/O hoàn thành (ví dụ kết nối đến) Windows sẽ phát hành một chuỗi chờ, nhưng chỉ khi số lượng các chuỗi chạy hiện thời (không bị chặn vì một lý do nào đó) nhỏ hơn giới hạn khả năng mở rộng được cấu hình cho cổng hoàn thành. Thông thường bạn sẽ thiết lập điều này thành một bội số nhỏ của số lõi.

2

Tôi muốn đề xuất phương pháp tiếp cận khác: Đề xuất của tôi chỉ sử dụng hai chuỗi. * một luồng kiểm tra các kết nối đang chờ. * Khi kết nối mới mở thông tin này được ghi vào cấu trúc dữ liệu được chia sẻ chứa tất cả các kết nối đang mở hiện tại. * Chủ đề thứ hai liệt kê cấu trúc dữ liệu đó và cho mỗi kết nối mở nhận dữ liệu được gửi và gửi trả lời.

Giải pháp này có khả năng mở rộng theo luồng hơn và nếu được triển khai thực hiện thì sẽ có hiệu suất tốt hơn, sau đó mở một chuỗi mới cho mỗi kết nối đã mở.

+0

này tôi sẽ nhớ, mặc dù tôi thực sự muốn trả lời mỗi kết nối đến ngay lập tức. Cám ơn vì sự gợi ý. –

+0

hi! @Dror Helper, đề nghị của bạn trông giống như tốt. Làm thế nào để thực hiện một chiến lược hiệu quả? Bạn có thể chia sẻ, bạn có đoạn mã nào không? – bashkan

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