Socket
int socket(int domain, int socket_type, int protocol);
소켓을 생성할 때는 위의 함수를 사용합니다.
domain은 소켓을 어떤 도메인으로 만들 것인지(AF_INET, AF_INET6(IPv6))를 결정하고
socket_type은 UDP 소켓인지 TCP 소켓인지, 다른 소켓 종류인지를 결정합니다.
protocol은 프로토콜 구성의 선택입니다. 이 함수는 커널에 네트워크를 사용해 소통할 수 있는 소켓을 생성합니다. socket의 parameter를 채우기 위해 getaddresssinfo의 결과물을 사용하거나 직접 입력해 줄 수 있습니다.
socket call은 정수를 반환합니다. 이 정수는 file descriptor입니다. 이 file descriptor로 read/write 함수를 사용해 패킷을 주고받을 수 있습니다.
TCP socket은 pipe와 유사합니다. 하지만 TCP socket은 pipe와 달리 양방향입니다. 즉, 데이터를 독립적으로 양방향으로 주거나 받을 수 있습니다.
connect
int coneectok = connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
connect에 socket file discriptor를 넘겨주면, 연결하기를 원하는 주소와 그 주소의 길이를 사용해 연결해줍니다. connect를 포함해 모든 네트워크 함수의 호출의 반환값을 확인해 에러를 체크하는 것이 좋습니다.
read/write
일단 connect에 성공하면 read/write를 통해 file descriptor처럼 사용이 가능합니다. 만약 웹사이트에 connect되었다면
의미있는 결과를 얻기 위해서는 http protocol 사양을 준수해야 한다는 것을 명심하세요. 이러한 일을 해주는 라이브러리가 존재하므로 소켓 레벨에서 connect하지 않을 수도 있습니다.
read나 write를 통해 쓴 바이트 수는 예상보다 작을 수 있습니다. 그러므로 read나 write의 반환값을 체크하는 것이 매우 중요합니다.
Complete Simple TCP Client Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
int main(int argc, char **argv) {
int s;
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
struct addrinfo hints, *result;
memset(&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_INET; /* IPv4 only */
hints.ai_socktype = SOCK_STREAM; /* TCP */
s = getaddrinfo("www.illinois.edu", "80", &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(1);
}
if (connect(sock_fd, result->ai_addr, result->ai_addrlen) == -1) {
perror("connect");
exit(2);
}
char *buffer = "GET / HTTP/1.0\r\n\r\n";
printf("SENDING: %s", buffer);
printf("===\n");
// For this trivial demo just assume write() sends all bytes in one go and is not interrupted
write(sock_fd, buffer, strlen(buffer));
char resp[1000];
int len = read(sock_fd, resp, 999);
resp[len] = '\0';
printf("%s\n", resp);
return 0;
}
예상 결과
SENDING: GET / HTTP/1.0
===
HTTP/1.1 200 OK
Date: Mon, 27 Oct 2014 19:19:05 GMT
Server: Apache/2.2.15 (Red Hat) mod_ssl/2.2.15 OpenSSL/1.0.1e-fips mod_jk/1.2.32
Last-Modified: Fri, 03 Feb 2012 16:51:10 GMT
ETag: "401b0-49-4b8121ea69b80"
Accept-Ranges: bytes
Content-Length: 73
Connection: close
Content-Type: text/html
Provided by Web Services at Public Affairs at the University of Illinois
Comment on HTTP request and response
위의 예는 Hypertest Transfer Protocol을 사용해 서버에 요청하는 예를 보여줍니다. 웹 페이지( 또는 다른 리소스)는 다음 요청을 사용합니다.
GET / HTTP/1.0
이 요청은 네개로 구성되어 있습니다.
첫번째로 GET, POST와 같은 method입니다.
두번째로 //index.html/image.png와 같은 resource입니다.
세번째는 HTTP//1.0 같은 프로토콜입니다.
마지막으로 2개의 new line입니다.(\r\n\r\n)
서버는 첫 번째 응답을 사용해 사용되는 HTTP 버전과 3자리 response code를 사용해 성공했는지 여부를 알려줍니다.
HTTP/1.1 200 OK
만약 클라이언트가 존재하지 않는 파일을 요청했다면, 첫 번째 응답은 잘 알려진 404 응답 코드를 보냅니다.
HTTP/1.1 404 Not Found
'Angrave System Programming > Networking' 카테고리의 다른 글
Networking: Nonboloking IO, select(), and epoll (0) | 2019.04.16 |
---|---|
Networking: Creating a UDP server (0) | 2019.04.16 |
Networking: Shutting down ports, reusing ports and other tricks (0) | 2019.04.11 |
Networking: Building a simple TCP Server (0) | 2019.04.10 |
POSIX: Error handling (0) | 2019.03.13 |