2010-01-05 22 views
5

Tôi đang chuyển một ứng dụng mạng của cửa sổ sang linux và gặp phải sự cố hết thời gian với cuộc gọi chọn trên linux. Các chức năng sau đây khối cho toàn bộ giá trị thời gian chờ và trả về trong khi tôi đã kiểm tra với một gói sniffer mà khách hàng đã gửi dữ liệu.Socket select() hoạt động trong Windows và hết giờ trong Linux

int recvTimeOutTCP(SOCKET socket, long sec, long usec) 
{ 
    struct timeval timeout; 
    fd_set fds;. 

    timeout.tv_sec = sec; 
    timeout.tv_usec = usec; 
    FD_ZERO(&fds); 
    FD_SET(socket, &fds); 

    // Possible return values: 
    // -1: error occurred 
    // 0: timed out 
    // > 0: data ready to be read 
    cerr << "Waiting on fd " << socket << endl; 
    return select(1, &fds, 0, 0, &timeout); 
} 

Trả lời

12

Tôi nghĩ tham số đầu tiên là select() phải là socket+1.

Bạn thực sự nên sử dụng một tên khác là socket cũng được sử dụng cho những thứ khác. Thường sử dụng sock.

+0

@jamessan Ah, vâng tôi có nghĩa là;) – epatel

+0

Vâng, cảm ơn, Điều đó đã giải quyết được vấn đề của tôi. –

+0

Phải. 'int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout);' where nfds là 'bộ mô tả tập tin được đánh số cao nhất trong bất kỳ bộ ba nào, cộng với 1'. – jamessan

2

Từ trang người đàn ông của chọn:

int select(int nfds, 
      fd_set* restrict readfds, 
      fd_set* restrict writefds, 
      fd_set* restrict errorfds, 
      struct timeval* restrict timeout); 

Các NFDS đầu tiên mô tả được kiểm tra trong mỗi bộ; tức là, các mô tả từ 0 đến nfds-1 trong các bộ mô tả được kiểm tra.

Do đó, tham số đầu tiên để lựa chọn nên ổ cắm + 1.

return select(socket + 1, &fds, 0, 0, &timeout); 
1

Tham số đầu tiên để select (...) là số mô tả tập tin để kiểm tra các thiết lập. Cuộc gọi của bạn đang yêu cầu nó chỉ nhìn vào bộ mô tả tập tin 0, mà gần như chắc chắn không phải là những gì socket được đặt thành.

2

select trên Windows bỏ qua tham số đầu tiên. Từ MSDN:

C++ 
int select(
    __in  int nfds, 
    __inout fd_set *readfds, 
    __inout fd_set *writefds, 
    __inout fd_set *exceptfds, 
    __in  const struct timeval *timeout 
); 

Parameters 

nfds [in] 

    Ignored. The nfds parameter is included only for 
    compatibility with Berkeley sockets. 
...
2

Vấn đề là fd_set trong linux là một mảng bit (ban đầu nó chỉ là int, nhưng sau đó bạn chỉ có thể xem 16 lần đầu tiên trong quy trình của bạn). Trong cửa sổ fd_set là một mảng các ổ cắm có độ dài ở phía trước (đó là lý do tại sao các cửa sổ không cần biết có bao nhiêu bit để xem).

Hàm poll() lấy một mảng bản ghi để xem trên linux và có các lợi ích khác làm cho nó trở thành lựa chọn tốt hơn so với select().

int recvTimeOutTCP(SOCKET socket, long msec) 
{ 
    int iret ; 
    struct polldf sockpoll ; 

    sockpoll.fd= socket ; 
    sockpoll.events= POLLIN ; 

    return poll(& sockpoll, 1, msec) ; 
} 
+0

Cảm ơn bạn đã các thông tin, là cuộc thăm dò này() chức năng nền tảng chéo bởi bất kỳ cơ hội? –

+0

Hmm, trên Linux bạn thực sự muốn sử dụng epoll, tốt nhất là ở chế độ kích hoạt cạnh. –

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