Как проверить что сокет отконнектился?

Тема в разделе "WASM.NETWORKS", создана пользователем slow, 8 авг 2006.

  1. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    Почему-то поток при дисконнекте сокета не закрывается, хотя должен. Подскажите в чем собака.

    Код (Text):
    1. ;--- process client
    2. ClientThreadProc proc ClientSock: SOCKET
    3.  
    4.     LOCAL buf[1024]: BYTE
    5.     LOCAL BufSz: DWORD
    6.     LOCAL ff: BOOL
    7.  
    8.     mov eax, TRUE
    9.     mov ff, eax
    10.     invoke setsockopt, ClientSock, SOL_SOCKET, SO_KEEPALIVE, addr ff, sizeof BOOL
    11.  
    12.     invoke ReceiveBuffer, ClientSock, addr buf, sizeof Password
    13.     invoke lstrcmp, addr buf, addr Password
    14.  
    15.     .IF eax != 0
    16.         invoke DestroySocket, ClientSock
    17.         ret
    18.     .ENDIF
    19.  
    20.     invoke SendBuffer, ClientSock, addr helo, sizeof helo
    21.  
    22.     .WHILE (TRUE)
    23.        
    24.         invoke ReceiveBuffer, ClientSock, addr BufSz, -1
    25.         invoke WSAGetLastError
    26.         .BREAK .IF eax != 0
    27.  
    28.         mov eax, BufSz
    29.  
    30.         .IF (eax>0)
    31.             invoke ReceiveBuffer, ClientSock, addr buf, BufSz    
    32.             invoke WSAGetLastError
    33.             .BREAK .IF eax != 0  
    34.        
    35.             invoke Parse, ClientSock, addr buf, BufSz
    36.         .ENDIF
    37.        
    38.         invoke Sleep, 60
    39.        
    40.     .ENDW
    41.  
    42.     ret
    43.  
    44. ClientThreadProc endp
    45.  
    46. ;--- receives buffer from socket
    47. ReceiveBuffer proc rSock: DWORD, BufAddr: DWORD, BufSize:DWORD
    48.  
    49.      LOCAL Result: DWORD
    50.  
    51.     .IF (BufSize == -1)
    52.         invoke ioctlsocket, rSock, FIONREAD, BufAddr
    53.         mov Result, eax
    54.     .ELSE
    55.         invoke recv, rSock, BufAddr, BufSize, 0
    56.         mov Result, eax
    57.     .ENDIF
    58.  
    59.     mov eax, Result
    60.     ret
    61.    
    62. ReceiveBuffer endp
    63.  
    64. ;--- sends buffer to socket
    65. SendBuffer proc wSock: DWORD, BufAddr: DWORD, BufSize: DWORD
    66.  
    67.     invoke send, wSock, BufAddr, BufSize, 0
    68.     ret
    69.  
    70. SendBuffer endp
     
  2. Bert

    Bert New Member

    Публикаций:
    0
    Регистрация:
    11 май 2005
    Сообщения:
    20
    Адрес:
    Russia
    Есть предположение. Правда, пока проверить по тех. причинам не могу.

    1. Сокет со стороны отправителя закрылся.
    2. invoke ReceiveBuffer, ClientSock, addr BufSz, -1 приводит к
    invoke ioctlsocket, rSock, FIONREAD, BufAddr
    Как реагирует ioctlsocket в данной ситуации? MSDN внятно про такую ситуацию ничего не говорит. Из списка ошибок самая подходящая - WSAENETDOWN.
    Но, имхо, ioctlsocket() никак не отслеживает такую ситуацию и просто записыват в BufSz ноль без какой-либо ошибки, что, вобщем-то, логично.
    3. .IF (eax>0) не проходит, так как eax = 0.

    В результате имеем бесконечный .WHILE(TRUE).
     
  3. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    Так оно и происходит. Я проверил :) Но дело в том что ошибки никакой нет, как вы правильно упомянули. При этом: я же делаю
    Код (Text):
    1.  invoke setsockopt, ClientSock, SOL_SOCKET, SO_KEEPALIVE, addr ff, sizeof BOOL
    т.е. по MSDn при отпадении сокета при любой сокетной операции (хотя бы select) должна возвратиться ошибка. Может, я неправильно применяю setsockopt?
     
  4. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    Наверное, надо поприменять select? А тогда, макросов FD_SET и FD_ZERO для масм ни у кого не завалялось?
     
  5. Bert

    Bert New Member

    Публикаций:
    0
    Регистрация:
    11 май 2005
    Сообщения:
    20
    Адрес:
    Russia
    Из MSDN про SO_KEEPALIVE:
    Однако ioctlsocket() такие ошибки не возвращает. Так что здесь SO_KEEPALIVE бесполезна.

    Вот тебе из linux kernel пример нужных макросов, может, поможет.
    Код (Text):
    1. #define __NFDBITS (8 * sizeof(unsigned long))
    2. #define __FD_SETSIZE 1024
    3. #define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS)
    4.  
    5. typedef struct {
    6.         unsigned long fds_bits [__FDSET_LONGS];
    7. } __kernel_fd_set;
    8.  
    9. #define __FD_SET(fd, fdsetp) \
    10.     __asm__ __volatile__("btsl %1,%0": \
    11.         "+m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
    12.  
    13. #define __FD_CLR(fd, fdsetp) \
    14.     __asm__ __volatile__("btrl %1,%0": \
    15.         "+m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
    16.  
    17. #define __FD_ISSET(fd, fdsetp) (__extension__ ({ \
    18.     unsigned char __result; \
    19.     __asm__ __volatile__("btl %1,%2 ; setb %0" \
    20.         :"=q" (__result) :"r" ((int) (fd)), \
    21.         "m" (*(__kernel_fd_set *) (fdsetp))); \
    22.     __result; }))
    23.  
    24. #define __FD_ZERO(fdsetp) \
    25.     do { \
    26.         int __d0, __d1; \
    27.         __asm__ __volatile__("cld ; rep ; stosl" \
    28.             :"=m" (*(__kernel_fd_set *) (fdsetp)), \
    29.             "=&c" (__d0), "=&D" (__d1) \
    30.             :"a" (0), "1" (__FDSET_LONGS), \
    31.             "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
    32.     } while (0)
     
  6. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    Bert =-O неплохо бы еще понять что тут написано ))
    буду пробовать с select, спасибо за совет
     
  7. Mybedy

    Mybedy New Member

    Публикаций:
    0
    Регистрация:
    30 май 2006
    Сообщения:
    1
    Адрес:
    Russia
  8. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    спсб, Mybedy