반응형
connect(2)
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
서버의 주소(addr)로 접속하여 connection을 유지합니다. connect(2) 함수는 socket(2)의 type 설정시 SOCK_STREAM, SOCK_SEQPACKET 등으로 설정된 connection-base socket의 경우에만 가능합니다. 두번째 파라미터인 struct sockaddr는 Address Family에 따라서 다른 구조체를 갖습니다. (참조: struct sockaddr - Address Family에 따른 구조체)
파라미터
sockfd
- socket(2)의 두번째 parameter인 type이 SOCK_STREAM, SOCK_SEQPACKET으로 생성한 socket descriptor.
addr
- socket에 설정할 주소 정보에 대한 struct입니다.
struct sockaddr는 socket을 지원하는 Protocol의 기본 골격에 대한 sturct 이며,
AF_* (Address Family)에 따라서 struct를 다르게 정의하여 사용합니다.
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
로 sa_family에 AF_*값을 설정하고 AF_*값에 따라서 sa_data의 구조가 다릅니다.
따라서 AF_*값에 따라서 구조체를 재정의하여 사용하며,
Address Family에 따라서 char sa_data[14]; 즉, 14 바이트보다 큰 경우가 있으므로
사실상 struct sockaddr은 의미가 없는 구조체입니다.
addrlen
- addr 구조체의 크기를 저장한 변수입니다. (AF_* 상수에 따라 크기가 다름)
RETURN
-1이 아님
- 정상적으로 connection되었습니다.
-1
- 오류가 발생하였으며, 상세한 오류는 errno에 저장됩니다.
EACCES : AF_UNIX, AF_LOCAL에서 directory 또는 file에 대한 권한이 없음.
EACCES, EPERM : socket에 broadcasting flag없이 broadcasting으로 접속시도함.
EADDRINUSE : local 주소를 이미 사용중임.
EAFNOSUPPORT : struct sockaddr의 sa_family field의 값을 잘못 설정함.
EAGAIN : struct sockaddr의 sa_family field의 값이 AF_INET일 때, 사용할 local port가 없는 경우
EALREADY : socket이 nonblocking으로 설정되고 이미 connection 시도를 한 경우
EBADF : sockfd가 유효하지 않은 경우
ECONNREFUSED : 서버 소켓이 listen 상태가 아니거나 방화벽으로 막혔을 때.
EFAULT : The socket structure address is outside the user's address space.
EINPROGRESS : socket이 nonblocking이고 바로 접속할 수 없을 때.
EINTR : signal이 발생하여 catch된 경우 (재시도 필요)
EISCONN : 이미 connect됨.
ENETUNREACH : Network이 도달할 수 없음
ENOTSOCK : socket descriptor가 아님.
ETIMEDOUT : 접속시 timeout 발생함.
활용 예제
Sample 1. TCP/IP connect by domain name
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 6905
#define SERVER_NAME "job.mydomain.com"
......
struct hostent *he;
struct sockaddr_in server_addr;
int sock;
......
if((he = gethostbyname(SERVER_NAME)) == NULL) {
fprintf(stderr, "%s는 등록되지 않은 서버명입니다.\n", SERVER_NAME);
return -1;
}
memset(&server_addr, 0x00, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
memcpy(&server_addr.sin_addr.s_addr, he->h_addr, he->h_length);
server_addr.sin_port = htons(SERVER_PORT);
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "Socket 생성 오류: %s\n", strerror(errno));
return -1;
}
if(connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Connection Error: %s\n", strerror(errno));
close(sock);
return -1;
}
......
Sample 2. TCP/IP connect by IP address
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_NAME "127.0.0.1"
#define SERVER_PORT 6905
......
struct sockaddr_in server_addr;
int sock;
......
memset(&server_addr, 0x00, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_NAME);
server_addr.sin_port = htons(SERVER_PORT);
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "Socket 생성 오류: %s\n", strerror(errno));
return -1;
}
if(connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Connection Error: %s\n", strerror(errno));
close(sock);
return -1;
}
......
see also : Socket 통신과 Socket 응용
반응형
'C언어 header > sys | socket.h' 카테고리의 다른 글
getpeername(2) - who are you? (너는 누구니?) (0) | 2019.09.29 |
---|---|
shutdown(2) - 읽기 / 쓰기 금지 설정 (0) | 2019.09.29 |
accept(2) / accept4(2) - client와 연결된 새로운 socket 생성 (0) | 2019.09.29 |
listen(2) - client가 접속할 수 있도록 준비 작업 (0) | 2019.09.29 |
struct sockaddr - Address Family에 따른 구조체 (0) | 2019.09.29 |