반복 실행 서버를 기준으로 시행하였습니다.
반복 실행 서버란 서버 프로그램이 클라이언트의 요청을 직접 처리하는 서버입니다.
반복 실행 서버는 인터넷 소켓 TCP(SOCK_STREAM)를 이용해 통신하기에 이 부분을 캡처해볼 것입니다.
#include <sys/socket.h> // 소켓 프로그래밍에 필요한 함수 & 상수 정의
#include <unistd.h>
#include <netinet/in.h> // 인터넷 프로토콜을 위한 구조체 & 상수 정의
#include <arpa/inet.h> // 인터넷 주소 변환 함수들을 정의
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define PORTNUM 9001 // 9001 포트 지정
int main() {
char buf[256];
struct sockaddr_in sin, cli;
int sd, ns, clientlen = sizeof(cli);
memset((char *)&sin, '\0', sizeof(sin)); // 구조체 초기화
sin.sin_family = AF_INET; // 소켓 종류 AF_INET 지정 (ipv4)
sin.sin_port = htons(PORTNUM); // 포트 번호 지정
sin.sin_addr.s_addr = inet_addr("192.168.147.129"); // IP 주소 설정
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) { // ipv4 | TCP 사용
perror("socket");
exit(1);
}
if (bind(sd, (struct sockaddr *)&sin, sizeof(sin))) { // bind() 함수를 사용해 IP주소/포트 번호와 연결
perror("bind");
exit(1);
}
if (listen(sd, 5)) { // liten() 함수를 호출해 클라이언트의 요청을 받을 준비가 끝났음을 운영체제에 알림
perror("listen");
exit(1);
}
while (1) {
if ((ns = accept(sd, (struct sockaddr *)&cli, &clientlen)) == -1) {
perror("accept");
exit(1);
} // accept() 함수를 사용해 클라이언트의 요청이 올 때까지 기다림
sprintf(buf, "%s", inet_ntoa(cli.sin_addr));
printf("*** Send a Message to Client(%s)\n", buf); // 어떤 클라이언트가 서버로 접속했는지 확인 & 출력
strcpy(buf, "Welcome to Network Server!!"); // 서버에서 클라이언트로 보낼 간단한 환영 메시지를 작성
if (send(ns, buf, strlen(buf) + 1, 0) == -1) { // send() 함수를 사용해 클라이언트로 보낼 메시지를 보냄
perror("send");
exit(1);
}
if (recv(ns, buf, sizeof(buf), 0) == -1) { // 클라이언트가 보낸 메시지를 recv() 함수로 받아서 출력
perror("recv");
exit(1);
}
printf("** From Client : %s\n", buf);
close(ns);
}
close(sd); // 작업이 끝나면 소켓을 닫음
}
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h> // 네크워크 데이터베이스 관련 구조체 & 함수 정의
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define PORTNUM 9001 // 클라이언트도 서버와 같은 포트 번호 사용
int main() {
int sd;
char buf[256];
struct sockaddr_in sin;
memset((char *)&sin, '\0', sizeof(sin)); // 구조체 초기화
sin.sin_family = AF_INET;
sin.sin_port = htons(PORTNUM); // 서버의 포트번호 지정
sin.sin_addr.s_addr = inet_addr("192.168.147.129"); // 접속할 서버의 주소를 지정
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { // ipv4 | TCP 소켓을 생성
perror("socket");
exit(1);
}
if (connect(sd, (struct sockaddr *)&sin, sizeof(sin))) {
perror("connect");
exit(1);
} // 서버와 접속
if (recv(sd, buf, sizeof(buf), 0) == -1) { // 접속한 후 서버에서 보낸 메시지를 받아 출력
perror("recv");
exit(1);
}
printf("** From Server : %s\n", buf);
strcpy(buf, "I want a HTTP Service."); // 서버로 보낼 메시지를 복사한 후 메시지를 서버로 전송
if (send(sd, buf, sizeof(buf) + 1, 0) == -1) {
perror("send");
exit(1);
}
close(sd);
}
server파일과 client파일을 각각 다른 docker 파일에 올려 시행하였습니다.
같은 docker 서버 내에서는 캡처가 되지 않습니다.
네트워크 패킷 캡처 도구인 pcap은 네트워크 인터페이스 카드(NIC)에서 패킷을 캡처합니다. 따라서, pcap이 실행되는 시스템 내부에서 발생하는 통신(예: 로컬호스트 내에서의 통신)은 NIC를 거치지 않기 때문에 pcap으로 캡처가 되지 않습니다.

socket_server를 실행시킨 후
다른 docker에서

socket_client를 실행시키면 Welcome to Network Server!! 라는 메시지를 보냅니다.

서버에서 클라이언트에서 보낸 메시지를 받았고 클라이언트에게 다시 메시지를 보냅니다.

이 과정에서 pcap 파일을 실행하고 결과를 보면

서로 주고 받는 과정을 볼 수 있었습니다!