z



host A                     host B
     |                            |
 connect()                      LISTEN
     |     SYN                    |
     |--------------------------->|
  SYN_SENT                      |
     |                   SYN      |
     |<---------------------------|
 ESTABLISHED                  SYN_RECV   NOTE: incomplete connection
| | queue

     |                            |
     |     ACK                    |
     |--------------------------->|
     |                       ESTABLISHED
     |                            |
     |                            |
  host A                     host B
     |                            |
ESTABLISHED                  ESTABLISHED
     |                            |
  close()                         |
     |                            |
FIN_WAIT_1                        |
     |     FIN_ACK                |
     |--------------------------->|
 CLOSING                      CLOSE_WAIT
     |                            |
     |                   ACK      |
     |<---------------------------|
FIN_WAIT_2                        |
     .                            .
     .                            .
     .                            .
     |                (DATA)      |  이 단계에서는 DATA 를 보낼 수도 있고, 그렇지 않을
     |<---------------------------|  수도 있습니다.
     |                            |
     .                            .
     .                            .
  TIME_WAIT                       .
     .                            .
     .                          close()
     |                            |
     |                FIN_ACK     |
     |<---------------------------|
  TIMED_WAIT                  LAST_ACK
     |     ACK                    |
     |--------------------------->|
  (CLOSEED)                  (CLOSED)



- 정상이 아닌 상태
  - SYNC_RECV
    - LISTEN하는 서버쪽에서 나타나며 SYN를 받고 이에대한 SYN를 보냈으나 ACK를
받지 못한 상태

    - 정상적인 접속 요청이 아닌 flood 어택인 경우 혹은 remote가 보낸 ACK
세그멘트가 유실된 경우

  - CLOSE_WAIT
    - remote의 FIN을 받아는데도 local에서 close()를 호출하지 않은 상태
    - 현재 local이 CLOSE_WAIT라는 것은 read()호출시 리턴값이 -1으로 알 수 있다.
  - FIN_WAIT_1
    - local에서 close()를 호출했는데 이에 대한 ACK를 받지 못한 상태.
    - ACK 세그먼트의 유실이 원인
  - FIN_WAIT_2
    - local에서 close()를 호출했으나, remote에서 close()를 하지 않은 경우
  - TIME_WAIT
    - 갯수가 적은것은 정상
    - 갯수가 많을 경우는 FIN_WAIT_2에서 전이한 것으로, FIN_WAIT_2와 원인이 같다.
- 다시 짤막 정리
  - CLOSE_WAIT : local에서 close() 안한것.
  - FIN_WAIT_2, 다수의 TIME_WAIT : remote에서 close() 안한것
  - 이외 : 세그먼트의 유실(네트워크 문제) 혹은 어택

- 상태 정리
  - SYNC_SENT : local에서 connect()를 호출하고 SYN을 못받은 상태
  - SYNC_RECV : LISTEN 상태의 local에서 SYN을 받고,
이에 대한 SYN를 보냈으나 ACK를 받지 못한 상태

  - CLOSE_WAIT : local에서 FIN을 받았는데도  close()를 호출하지 않은것이다.
  - FIN_WAIT_1 : local에서 close()를 호출했는데, remote로 부터
ACK를 받지 못한것. 네트워크 문제

  - FIN_WAIT_2 : local에서 close()를 호출했는데, remote가 close()를
호출하지 않은것

  - TIME_WAIT : FIN_WAIT_2에서 일정시간 이후의 상태
 
  * TIME_WAIT는 정상적으로 발생할 수 있으나, 그 수가 많은 경우는 FIN_WAIT_2에서
전이한것이다.
- from man netstat
  ESTABLISHED
    The socket has an established connection.
  SYN_SENT
    The socket is actively attempting to establish a connection.
  SYN_RECV
    A connection request has been received from the network.
  FIN_WAIT1
    The socket is closed, and the connection is shutting down.
  FIN_WAIT2
   Connection is closed, and the socket is waiting for a shutdown
from the remote end.

  TIME_WAIT
    The socket is waiting after close to handle packets still in
the network.

  CLOSED
    The socket is not being used.
  CLOSE_WAIT
    The remote end has shut down, waiting for the socket to close.
  LAST_ACK
    The remote end has shut down, and the socket is closed.
Waiting for acknowledgement.

  LISTEN
    The socket is listening for incoming connections.
  CLOSING
    Both sockets are shut down but we still don't have all
our data sent.

  UNKNOWN
    The state of the socket is unknown.
=====================================================================



사용자 삽입 이미지










출처 및 참조: 자바서비스넷(이원영), 블로그(프론티어), 티스토리(천검)
AND

AND

#include <Winsock2.h>
#include <Iphlpapi.h>
#include <Icmpapi.h>
#include <stdio.h>
#include <windows.h>

bool sendIcmpEcho(TCHAR * dstAddr,  //목적지 IP Addr
     DWORD tmOut,                              //요청 타임아웃
     LPVOID pData,                             //데이터
     DWORD dataSize,                        //데이터 사이즈
     ULONG * status)                         //응답 상태코드
{
 HANDLE hIcmpFile = null;
 DWORD dwRetVal = 0;
 LPVOID ReplyBuffer = null;
 bool bRet  = false;

 if((hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
  return bRet;

 ReplyBuffer = (VOID*) new byte[sizeof(ICMP_ECHO_REPLY) + dataSize];

 if((dwRetVal = IcmpSendEcho(hIcmpFile, inet_addr(dstAddr), pData, dataSize,
     NULL, ReplyBuffer, dataSize + sizeof(ICMP_ECHO_REPLY), tmOut)) != 0)
 {
 
  /*
  ICMP_ECHO_REPLY * p = (ICMP_ECHO_REPLY *)ReplyBuffer;

  printf("st Address %d\n",p->Address);
  printf("st Status %d\n",p->Status);
  printf("st RoundTripTime %d\n",p->RoundTripTime);
  printf("st DataSize %d\n",p->DataSize);
  printf("st Reserved %d\n",p->Reserved);
  printf("st Data %s\n",p->Data);
  */
 
  bRet = !bRet;
  *status = ((ICMP_ECHO_REPLY *)ReplyBuffer)->Status;
 }

 delete[] ReplyBuffer;
 CloseHandle(hIcmpFile);

 return bRet;
}

Link to iphlpapi.lib, ws2_32.lib

별로 세밀한 제어?를 할 수는 없지만 .. ICMP Echo를 이용해 특별한 일을 할 일은 없을 듯 하여, 이 정도로도 충분히 사용가능 할듯하다. IcmpSendEcho2()를 이용하면 이벤트를 이용해
비동기 처리도 가능하다.

AND

InternetAttemptConnect

Attempts to make a connection to the Internet.

DWORD InternetAttemptConnect(
  DWORD dwReserved
);

Parameters

dwReserved
[in] Reserved. Must be zero.

Return Values

Returns ERROR_SUCCESS if successful, or a system error code otherwise.

Remarks

This function allows an application to first attempt to connect before issuing any requests. A client program can use this to evoke the dial-up dialog box. If the attempt fails, the application should enter offline mode.

Requirements

Client Requires Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0, Windows Me, Windows 98, or Windows 95.
Server Requires Windows Server 2003, Windows 2000 Server, or Windows NT Server 4.0.
Version Requires Internet Explorer 3.0 or later.
Header

Declared in Wininet.h.

Library

Link to Wininet.lib.

DLL Requires Wininet.dll.

See Also

Enabling Internet Functionality, WinINet Functions

AND

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/time.h>

typedef struct sockaddr_in sockaddr_in;
typedef struct timeval timeval;


int conn_without_select(int milli_interval, sockaddr_in * addr);
int conn_with_select(int milli_interval,  sockaddr_in * addr);

int main()
{

int sockfd;
sockaddr_in dest_addr;
char buf[48]={0};

dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(5200);
dest_addr.sin_addr.s_addr = inet_addr("59.25.xxx.xxx");
memset(&(dest_addr.sin_zero), 0, 8);

sockfd = conn_without_select(1000, &dest_addr);
//sockfd = conn_with_select(1000, &dest_addr);

if(sockfd < 0)
{
 printf("Time out or Other error\n");
 return 0;
}

memset(buf, 0, sizeof(char) * 48);

buf[0] = 0x50;
buf[1] = 0x54;
buf[2] = 0x50;
buf[3] = 0x45;

send(sockfd, buf, 4, 0);
recv(sockfd, buf, 20,0);
buf[20]=0;
printf("%s\n", buf);

close(sockfd);

return 0;
}

int conn_without_select(int milli_interval, sockaddr_in * addr)
{
int sockfd = -1;
int opts;
int retVal = 0;
char dummy = 0;
int nSend;
unsigned long sleep_interval = 10000;

if(milli_interval == 0)
 return -1;

milli_interval *= 1000;


sockfd = socket(AF_INET, SOCK_STREAM, 0);

opts = fcntl(sockfd, F_GETFL, 0);

if(fcntl(sockfd,F_SETFL,O_NONBLOCK) < 0)
 goto errLine;

if(connect(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr)) < 0 && errno == EINPROGRESS)
{

 do{
  usleep(sleep_interval);

  nSend = send(sockfd, (void *)&dummy, 0, MSG_NOSIGNAL);
 
  if(nSend < 0)
  {
   milli_interval -= sleep_interval;
  }
  else
  {
   if(fcntl(sockfd,F_SETFL,opts) < 0)
    goto errLine;
   else
    return sockfd;
  }

 }while(milli_interval > 0);

}
else
{
 return sockfd;
}

errLine:
if(sockfd > 0)
 close(sockfd);

return -1;
}

int conn_with_select(int milli_interval,  sockaddr_in * addr)
{

int sockfd = -1;
int opts;
fd_set socks;
timeval tv;
int retVal;
char dummy = 0;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

opts = fcntl(sockfd, F_GETFL, 0);

if(fcntl(sockfd,F_SETFL,O_NONBLOCK) < 0)
 goto errLine;

if(connect(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr)) < 0 && errno == EINPROGRESS)
{

 memset(&tv, 0, sizeof(timeval));
 tv.tv_sec = milli_interval;
 tv.tv_usec = 0;

 FD_ZERO(&socks);
 FD_SET(sockfd, &socks);
 
 retVal = select(sockfd + 1, (fd_set *)0, (fd_set *) &socks, (fd_set *)0 , &tv);

 if(retVal)
 {
  if(FD_ISSET(sockfd,&socks))
  {
   if(fcntl(sockfd,F_SETFL,opts) < 0)
   {
    goto errLine;
   }
   else
   {

    if(send(sockfd, (void *)&dummy, 0, 0) < 0)
    {
     goto errLine;
    }

    return sockfd;
   }
  } 
 }
 else
 {
  goto errLine;
 }

}
else
{
 return sockfd;
}

errLine:
if(sockfd > 0)
 close(sockfd);

return -1;
}

AND