Linux 네트워크 프로 그래 밍 의 connect 함수 분석

CLIENT / SERVER 모델 의 네트워크 응용 에서 클 라 이언 트 의 호출 순 서 는 대체적으로 다음 과 같다.
        socket -> connect -> recv/send -> close
        그 중에서 socket 은 의심 할 만 한 것 이 없습니다. 주로 서버 와 데 이 터 를 교환 하 는 소켓 을 만 들 고 빠르게 돌아 갑 니 다. 이때 데 이 터 는 네트워크 카드 를 통 해 보 내지 않 고 그 다음 에 connect 함 수 는 네트워크 데 이 터 를 보 냅 니 다. TCP 의 세 번 의 악수 도 바로 이때 부터 connect 는 먼저 SYN 가방 을 서버 에 보 냅 니 다.그리고 최초의 CLOSED 상태 에서 SYNSENT 상태, 이 상태 에서 서버 의 확인 패 키 지 를 기다 리 고 있 습 니 다. 보통 이 확인 패 키 지 는 곧 도착 하기 때문에 netstat 명령 으로 SYN 을 볼 수 없습니다.SENT 상태의 존 재 는 극단 적 인 상황 에 대한 시 뮬 레이 션 을 통 해 클 라 이언 트 로 하여 금 임의로 지정 한 서버 (예 를 들 어 IP 주 소 는 88.8.8 8.8) 에 연결 하 게 할 수 있 습 니 다. 이 서버 는 SYN 가방 의 확인 가방 (SYN ACK) 에 피드백 하지 않 기 때문에 클 라 이언 트 는 일정한 시간 안에 SYN 에 있 을 것 입 니 다.SENT 상태 이 며, 예 정 된 시간 초과 (예 를 들 어 3 분) 이후 connect 함수 에서 되 돌 아 옵 니 다. connect 호출 이 실패 하면 (ESTABLISHED 상태 에 도달 하지 못 함) 이 소켓 을 사용 할 수 없습니다. connect 함 수 를 다시 호출 하려 면 socket 함 수 를 다시 사용 하여 새 소켓 을 만들어 야 합 니 다.
다음은 실례 분석 을 결합 하여 클 라 이언 트 코드 는 다음 과 같다.
/**
 * client.c
 *
 * TCP client program, it is a simple example only.
 * Writen By: Zhou Jianchun
 * Date: 2011.08.11
 *
 * Compiled With: gcc -o client client.c
 * Tested On: Ubuntu 11.04 LTS
 * gcc version: 4.5.2
 *
 */

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

#define SERVER_PORT 20000

void usage(char *name)
{
	printf("usage: %s IP
", name); } int main(int argc, char **argv) { int server_fd, client_fd, length = 0; struct sockaddr_in server_addr, client_addr; socklen_t socklen = sizeof(server_addr); if(argc < 2) { usage(argv[0]); exit(1); } if((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("create socket error, exit!
"); exit(1); } srand(time(NULL)); bzero(&client_addr, sizeof(client_addr)); client_addr.sin_family = AF_INET; client_addr.sin_addr.s_addr = htons(INADDR_ANY); bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; inet_aton(argv[1], &server_addr.sin_addr); server_addr.sin_port = htons(SERVER_PORT); if(connect(client_fd, (struct sockaddr*)&server_addr, socklen) < 0) { printf("can not connect to %s, exit!
", argv[1]); printf("%s
", strerror(errno)); exit(1); } return 0; }

컴 파일 완료 후 실행:
zhou@neptune:~/data/source$ ./client 88.88.88.88

이 때 프로그램 은 connect 함수 에서 대기 시간 을 막 고 약 180 초 후에 출력 합 니 다.
can not connect to 88.88.88.88, exit!
Connection timed out

현재 connect 의 반환 값 은 ETIMEOut 입 니 다.
이 과정 에서 우 리 는 netstat 명령 으로 연결 상 태 를 조회 할 수 있 습 니 다.
zhou@neptune:~/data/source$ sudo netstat -natp |grep 20000
tcp        0      1 192.168.0.4:44203       88.88.88.88:20000       SYN_SENT    5954/client    

이때 TCP 연결 상 태 를 SYN 으로 볼 수 있 습 니 다.SENT 는 SYN 가방 을 발송 한 후 서버 로부터 SYN ACK 가방 을 돌려 받 지 못 했다 는 뜻 이다.
그 다음 에 우 리 는 이 클 라 이언 트 프로그램 을 사용 하여 자신의 기 계 를 연결 합 니 다. 테스트 할 때 나의 IP 주 소 는 192.168.0.4 이 고 무선 랜 입 니 다. 결 과 는 다음 과 같 습 니 다.
zhou@neptune:~/data/source$ ./client 192.168.0.4
can not connect to 192.168.0.4, exit!
Connection refused

내 기기 에 지정 한 포트 (20000) 에서 감청 하 는 서버 프로그램 이 실행 되 지 않 았 기 때문에 이 연결 은 프로 토 콜 스 택 에서 직접 거부 되 었 습 니 다 (RST 형식의 TCP 패 키 지 를 보 내 는 것 을 통 해). connect 는 즉시 되 돌아 오고 값 은 ECONNREFUSED 입 니 다.
같은 랜 에 존재 하지 않 는 호스트 를 연결 할 때의 상황 을 살 펴 보 자. 예 를 들 어 이 상상 하 는 호스트 의 IP 주 소 는 192.168.0.188 이다.
zhou@neptune:~/data/source$ ./client 192.168.0.188
can not connect to 192.168.0.188, exit!
No route to host

로 컬 랜 에 있 는 이 호스트 가 존재 하지 않 기 때문에 ARP 요청 이 응답 하지 않 습 니 다. 게 이 트 웨 이 는 호스트 가 접근 할 수 없 는 ICMP 메시지 에 응답 하고 connect 는 EHostUNREACH 로 돌아 갑 니 다.
이로써 connect 함수 에 대한 분석 은 끝 났 습 니 다. 본인 의 수준 이 제한 되 어 있 기 때문에 블 로그 의 부적 절하 거나 잘못된 점 이 불가피 합 니 다. 독자 의 비판 과 지적 을 간절히 바 랍 니 다. 또한 독자 가 관련 내용 을 공동으로 토론 하 는 것 도 환영 합 니 다. 기꺼이 교류 하고 싶다 면 귀중 한 의견 을 남 겨 주 십시오. 감사합니다.

좋은 웹페이지 즐겨찾기