2010-01-06 25 views
11

Dường như sử dụng socket.Close() cho một socket tcp, không đóng hoàn toàn socket. Trong ví dụ sau, tôi đang cố gắng kết nối với example.com tại cổng 9999, không được mở và sau một khoảng thời gian chờ ngắn, tôi đang cố gắng đóng socket.Socket.Close không thực sự đóng socket tcp? (C#)

for (int i = 0; i < 200; i++) 
    { 
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    sock.LingerState = new LingerOption(false, 0); 
    sock.BeginConnect("www.example.com", 9999, OnSocketConnected, sock); 
    System.Threading.Thread.Sleep(50); 
    sock.Close(); 
    } 

Nhưng khi tôi hãy nhìn vào netstat sau khi vòng lặp hoàn thành, tôi thấy rằng có rất nhiều ổ cắm nửa mở:

TCP israel-xp:6506   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6507   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6508   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6509   www.example.com:9999 SYN_SENT 

EDIT . Ok, một số ngữ cảnh bị thiếu. Tôi đang sử dụng beginconnect vì tôi mong đợi kết nối socket thất bại (9999 không được mở), và trong mã thực của tôi, tôi gọi socket.Close() khi bộ hẹn giờ được đặt. Trên OnSocketConnected tôi gọi EndConnect, mà ném một ngoại lệ (cố gắng gọi một phương thức của một đối tượng xử lý). Mục tiêu của tôi là có thời gian chờ ngắn cho giai đoạn kết nối socket.

Bất kỳ đầu mối nào tôi đang làm sai? Cảm ơn!

Trả lời

14

Nó sẽ đóng phần .NET của ổ cắm. Tuy nhiên, theo đặc tả TCP, hệ điều hành phải giữ cho các mức thấp hơn của ổ cắm mở trong một khoảng thời gian nhất định để phát hiện sự truyền lại và tương tự. Trong trường hợp đặc biệt này, nó có thể giữ ổ cắm xung quanh một chút để phát hiện một trả lời cho gói SYN được gửi để nó có thể trả lời hợp lý hơn và không trộn lẫn câu trả lời với các gói tin khác được gửi đi.

+2

có ý nghĩa, nhưng không phải là thiết lập linger để sai nên giải quyết nó? – r0u1i

+0

oh, nán lại không làm điều này. Vì vậy, không có thực sự là một cách để làm cho Windows chấm dứt socket. – r0u1i

+1

theo mặc định, nó sẽ ở trạng thái FIN_WAIT trong 4 phút trước khi Windows thực sự đóng nó lại. Thậm chí thú vị hơn là nếu bạn mở lại kết nối khác với cùng một cổng đích/cổng sẽ sử dụng lại các kết nối trong FIN_WAIT khớp với nhau. – Jay

10

Bạn đang gọi số *Begin*Connect - vì vậy hãy thực hiện không đồng bộ. Bạn hoàn toàn có thể cố gắng đóng socket trước khi nó kết nối - vì vậy khi nó kết nối, nó vẫn mở.

Thử kết nối đồng bộ - hoặc đóng kết nối theo số OnSocketConnected để bạn có thể thấy hiệu quả của việc đóng một ổ cắm được kết nối thực sự.

+0

Xem chỉnh sửa của tôi. Tôi đang sử dụng mục đích BeginConnect và mã thực sự của tôi chờ một khoảng thời gian chờ trước khi gọi Đóng. Chỉ cần gọi EndConnect trên ổ cắm như vậy (nơi cổng dest không mở), sẽ chỉ mất một thời gian * dài * để hoàn thành. Hay nói cách khác, tôi muốn hết thời gian chờ kết nối ổ cắm sau giai đoạn X mili giây (và không phải là số lượng cửa sổ mili giây cực kỳ cao theo mặc định). – r0u1i

18

Theo thiết kế, bạn nên luôn gọi Shutdown trước khi đóng ổ cắm.

mySocket.Shutdown(SocketShutdown.Both); 
mySocket.Close(); 

Làm như vậy vô hiệu hóa việc gửi và nhận trên ổ cắm, vì vậy nó sẽ không chấp nhận dữ liệu đến sau khi bạn đóng, ngay cả khi hệ điều hành vẫn có quyền kiểm soát.

Jon Skeet cũng có một điểm, rằng vì bạn đang mở kết nối không đồng bộ, nó thực sự có thể kết nối trong khi bạn đang cố gắng đóng nó. Tuy nhiên, nếu bạn gọi Shutdown trên đó, nó sẽ không cho phép nhận thông tin như bạn đang gặp phải.

Chỉnh sửa: Bạn chỉ có thể Shutdown ổ cắm đã được kết nối, vì vậy hãy ghi nhớ điều này khi bạn viết mã.

+0

+1 cho nhận xét về câu trả lời của Jon Skeet. :-) –

+0

ShutDown sẽ ném một lỗi nếu ổ cắm chưa được kết nối - đó chính xác là kịch bản của tôi. – r0u1i

+0

Sau đó, bạn nên sử dụng OnSocketConnected để gọi ShutDown trên nó và đóng nó, hoặc một cái gì đó của bản chất đó. –

0

Bạn đang khởi tạo một Ổ cắm mới trong mỗi Vòng lặp ... với * .close() bạn đóng cũ và lúc bắt đầu bạn đang tạo một cái mới với các tham số giống như Socket trước đó.

+0

có. nhưng tôi thấy nhiều ổ cắm mở hơn chỉ một cái. – r0u1i

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