CSAPP 11. Network Programming
22360 ワード
ジャングルでc言語でWebサーバ,コード,CSAPP書の第11章を実現した.ジャングルで駐車Webサーバーを習った内容を整理したいです.
マットの上で整理した后に持ってきた部分のイメージがあまり良くなくてあるいは笔记がとても乱れています...
1. The Client-Server Programming Model
A server manages some resource, and it provides some service for its clients by manipulating that resource.
サーバは、リソースを管理し、リソースを管理してクライアントにサービスを提供します.
クライアントとは?
サービスを利用するユーザまたはユーザの端末を指す.
サーバとは
サービスを提供するコンピュータであり、多くのクライアントに存在するため、通常は非常に大きな容量とパフォーマンスを有します.しかし,最近ではサーバの役割とクライアントの機能を同時に果たす環境が数多く出現している.
クライアント-サーバの基本トランザクション.
ネットワーク
ネットワークとは
A computer network is a set of computers sharing resources located on or provided by network nodes.
これは、ネットワークノード(endpoint)によって提供されるリソースを共有するためのコンピュータの集合を意味する.
ネットワークはホストごとにI/Oデバイスとして認識される.I/Oバス拡張スロットを挿入するアダプタは、ネットワークに物理的なインタフェースを提供します.ネットワークから受信したデータはI/Oとメモリバスを経由し、アダプタからメモリに至るまで、通常DMA方式でコピーされる.
物理的には、ネットワークは階層を持つシステムです.ネットワークは学習を必要とする領域であるが,この本はHost‐Hub‐Bridgeの階層構造を有することを示す簡潔に紹介した.ブリッジとブリッジの間でルータを介してデータを転送します.
服役中に隣の中隊から撤退して大掃除をしたのを覚えていますが、黄色い太い網が深さいっぱいの網橋に差し込まれた電源線を抜いて行ってしまい、しばらくネットが途切れて指揮官たちがひっくり返ってしまいました.
これにより、ホストとホストの間でネットワークを介して通信すると、トランスポート層はホスト内のプロセスとプロセスとの間の通信を行う
可能にする.IPアドレスは唯一の端末アドレスである.これはホームアドレスの概念であり、コンピュータ上で複数のプロセスが実行されている可能性があり、IPアドレスの後ろのPortに渡される.
Socket Interface
ソケットとは?
ソケットは、ネットワーク上の2つのプロセスが双方向に通信できる装置です.
カーネルの場合、ソケットは開いているファイルです.ファイルの読み取り/書き込みにより、他のプロセスと通信できます.
では、コンセントのインターフェースは?
ソケットインタフェースは、アプリケーション間のネットワークを構成するための関数の集合です.
クライアントは、getaddrinfo
を介してupd方式でサーバのIPアドレスを受信する.int socket(int domain, int type, int protocol);
このアドレスをパラメータとしてsocketを生成し、connect
関数を実行する. int connect(int clientfd, const struct sockaddr *addr, socklen_t addrlen);
最初のパラメータは、socket関数として返されるclientfd
をパラメータとして受信し、サーバへの接続を試みます.connect
関数は、接続が成功する前にブロックされ、成功した場合、clientfd
はサーバ上のconnfd
に接続され、ファイルを読み取り/書き込みますが、接続に失敗した場合は-1に戻ります.
サーバがソケットを作成した後、bind関数を使用してサーバのIP、ポートアドレスをそのソケットにバインド(貼り付け)する必要があります.int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
最初は、クライアントが要求をサーバアドレスに送信する機会があり、サーバがなぜ自分のアドレスをバインドするのか、サーバコンピュータの立場で複数のプロセスを実行し、異なるアドレスを区別するために異なるポート番号が必要になるため、独自のソケットが作成されます.int listen(int sockfd, int backlog);
その後、最初のパラメータはbind関数であり、listen関数を実行するために割り当てられたアドレスのsocketfd
を受信し、サーバがクライアントから要求を送信し、接続に成功するように要求すると、サーバ側はconnfd
を生成し、クライアント側はclientfd
を生成する.backlog
に送信される第2のパラメータは、client
によって送信されるパケットがキューに入り、backlogのサイズを最大限に保持することができる.tcp方式では、キューにbacklogがあればパケットが失われ、サーバに要求を送信する必要がある.(遅くなる)
コード#コード#
クライアントとサーバのプライマリ・プライマリ・コード.
Client
int open_clientfd(char *hostname, char *port) {
int clientfd, rc;
struct addrinfo hints, *listp, *p;
/* potential server addresses 리스트 설정 */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* 연결 설정 */
hints.ai_flags = AI_NUMERICSERV; /* port를 숫자로 받기. */
hints.ai_flags |= AI_ADDRCONFIG; /* Recommended for connections */
if ((rc = getaddrinfo(hostname, port, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo failed (%s:%s): %s\n", hostname, port, gai_strerror(rc));
return -2;
}
/* 연결될 때 까지 addr 가 나온 구조체를 돌면서 연결 요청 */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((clientfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) // 소캣 생성
continue;
/* Connect to the server */
if (connect(clientfd, p->ai_addr, p->ai_addrlen) != -1) // 서버에 연결을 요청
break;
if (close(clientfd) < 0) { /* 연결 닫기 */
fprintf(stderr, "open_clientfd: close failed: %s\n", strerror(errno));
return -1;
}
}
/* 구조체 정리 */
freeaddrinfo(listp);
if (!p) /* All connects failed */
return -1;
else /* The last connect succeeded */
return clientfd;
}
server
int open_listenfd(char *port)
{
struct addrinfo hints, *listp, *p;
int listenfd, rc, optval=1;
/* server addresses 설정*/
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* SOCK_STREAM */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* IP Address */
hints.ai_flags |= AI_NUMERICSERV;
if ((rc = getaddrinfo(NULL, port, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo failed (port %s): %s\n", port, gai_strerror(rc));
return -2;
}
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) // 소켓을 생성
continue; /* Socket failed, try the next */
/* "Address already in use" error 해제 */
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
/* Bind the descriptor to the address */
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) // 해당 소켓을 listenfd 에 bind 처리함
break; /* Success */
if (close(listenfd) < 0) { /* Bind failed, try the next */
fprintf(stderr, "open_listenfd close failed: %s\n", strerror(errno));
return -1;
}
}
freeaddrinfo(listp);
if (!p) /* No address worked */
return -1;
/* listen 상태로 client 기다리기 */
if (listen(listenfd, LISTENQ) < 0) {
close(listenfd);
return -1;
}
return listenfd;
}
Reference
この問題について(CSAPP 11. Network Programming), 我々は、より多くの情報をここで見つけました
https://velog.io/@jungbumwoo/CSAPP-Labsyzf-proxylab-handout-3eproxy-Part-1.c
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
ソケットとは?
ソケットは、ネットワーク上の2つのプロセスが双方向に通信できる装置です.
カーネルの場合、ソケットは開いているファイルです.ファイルの読み取り/書き込みにより、他のプロセスと通信できます.
では、コンセントのインターフェースは?
ソケットインタフェースは、アプリケーション間のネットワークを構成するための関数の集合です.
クライアントは、
getaddrinfo
を介してupd方式でサーバのIPアドレスを受信する.int socket(int domain, int type, int protocol);
このアドレスをパラメータとしてsocketを生成し、connect
関数を実行する. int connect(int clientfd, const struct sockaddr *addr, socklen_t addrlen);
最初のパラメータは、socket関数として返されるclientfd
をパラメータとして受信し、サーバへの接続を試みます.connect
関数は、接続が成功する前にブロックされ、成功した場合、clientfd
はサーバ上のconnfd
に接続され、ファイルを読み取り/書き込みますが、接続に失敗した場合は-1に戻ります.サーバがソケットを作成した後、bind関数を使用してサーバのIP、ポートアドレスをそのソケットにバインド(貼り付け)する必要があります.
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
最初は、クライアントが要求をサーバアドレスに送信する機会があり、サーバがなぜ自分のアドレスをバインドするのか、サーバコンピュータの立場で複数のプロセスを実行し、異なるアドレスを区別するために異なるポート番号が必要になるため、独自のソケットが作成されます.int listen(int sockfd, int backlog);
その後、最初のパラメータはbind関数であり、listen関数を実行するために割り当てられたアドレスのsocketfd
を受信し、サーバがクライアントから要求を送信し、接続に成功するように要求すると、サーバ側はconnfd
を生成し、クライアント側はclientfd
を生成する.backlog
に送信される第2のパラメータは、client
によって送信されるパケットがキューに入り、backlogのサイズを最大限に保持することができる.tcp方式では、キューにbacklogがあればパケットが失われ、サーバに要求を送信する必要がある.(遅くなる)コード#コード#
クライアントとサーバのプライマリ・プライマリ・コード.
Client
int open_clientfd(char *hostname, char *port) {
int clientfd, rc;
struct addrinfo hints, *listp, *p;
/* potential server addresses 리스트 설정 */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* 연결 설정 */
hints.ai_flags = AI_NUMERICSERV; /* port를 숫자로 받기. */
hints.ai_flags |= AI_ADDRCONFIG; /* Recommended for connections */
if ((rc = getaddrinfo(hostname, port, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo failed (%s:%s): %s\n", hostname, port, gai_strerror(rc));
return -2;
}
/* 연결될 때 까지 addr 가 나온 구조체를 돌면서 연결 요청 */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((clientfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) // 소캣 생성
continue;
/* Connect to the server */
if (connect(clientfd, p->ai_addr, p->ai_addrlen) != -1) // 서버에 연결을 요청
break;
if (close(clientfd) < 0) { /* 연결 닫기 */
fprintf(stderr, "open_clientfd: close failed: %s\n", strerror(errno));
return -1;
}
}
/* 구조체 정리 */
freeaddrinfo(listp);
if (!p) /* All connects failed */
return -1;
else /* The last connect succeeded */
return clientfd;
}
server
int open_listenfd(char *port)
{
struct addrinfo hints, *listp, *p;
int listenfd, rc, optval=1;
/* server addresses 설정*/
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* SOCK_STREAM */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* IP Address */
hints.ai_flags |= AI_NUMERICSERV;
if ((rc = getaddrinfo(NULL, port, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo failed (port %s): %s\n", port, gai_strerror(rc));
return -2;
}
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) // 소켓을 생성
continue; /* Socket failed, try the next */
/* "Address already in use" error 해제 */
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
/* Bind the descriptor to the address */
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) // 해당 소켓을 listenfd 에 bind 처리함
break; /* Success */
if (close(listenfd) < 0) { /* Bind failed, try the next */
fprintf(stderr, "open_listenfd close failed: %s\n", strerror(errno));
return -1;
}
}
freeaddrinfo(listp);
if (!p) /* No address worked */
return -1;
/* listen 상태로 client 기다리기 */
if (listen(listenfd, LISTENQ) < 0) {
close(listenfd);
return -1;
}
return listenfd;
}
Reference
この問題について(CSAPP 11. Network Programming), 我々は、より多くの情報をここで見つけました https://velog.io/@jungbumwoo/CSAPP-Labsyzf-proxylab-handout-3eproxy-Part-1.cテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol