250929

lililllilillll·2025년 9월 29일

개발 일지

목록 보기
309/350

✅ 한 것들


  • 윤성우의 열혈 TCP/IP 소켓 프로그래밍
  • 코딩 인터뷰 완전 분석


📖 윤성우의 열혈 TCP/IP 소켓 프로그래밍


Chapter 04 TCP 기반 서버/클라이언트 1

04-1 TCP와 UDP에 대한 이해

TCP (Transmission Control Protocol) 소켓

  • 연결 지향, 스트림 기반
  • APPLICATION 계층 → TCP 계층 → IP 계층 → LINK 계층

LINK 계층 : 물리적인 연결
IP 계층 : 데이터 전송 경로를 위한 프로토콜
TCP/UDP 계층 : IP계층 경로 정보 바탕으로 데이터 송수신
APPLICATION 계층 : 클라 서버 송수신 관한 규칙

04-2 TCP 기반 서버, 클라 구현

TCP 서버 함수 호출 순서

  • socket() : 소켓 생성
  • bind() : 소켓 주소 할당
  • listen() : 연결 요청 대기 상태
  • accept() : 연결 허용
  • read() / write() : 데이터 송수신
  • close() : 연결 종료

listen() 호출하면 클라 연결 요청 받기 시작한다
연결요청 대기 큐에 연결 요청이 클라가 호출한 connect()를 통해 들어온다
서버가 accept()를 하면 서버 소켓과 별도인 소켓이 새로 만들어져 연결 성립

TCP 클라 함수 호출 순서

  • socket() : 소켓 생성
  • connect() : 연결 요청
  • read()/write() : 데이터 송수신
  • close() : 연결 종료

connect() 함수 반환 조건

  • 서버에 의해 연결 요청 접수 (accept() 등록이 아니라 대기 큐에 들어왔다는거)
  • 네트워크 단절 등 오류 발생하여 연결 요청 중단

클라 소켓 주소 정보는 어디에?

  • 서버 소켓에는 IP와 PORT를 할당한다
  • 클라에선 bind()로 소켓에 자기 주소와 자기 PORT 할당 하지 않는다
  • connect()에서 커널이 알아서 자기 주소와 임의 PORT 할당

04-3 Iterative 기반의 서버, 클라 구현

반복문을 삽입해서 여러 클라에게 accept()문 호출 및 read(), write()
서버 소켓이 아니라 accept()에서 생성된 소켓을 close()까지
한 번에 하나의 클라가 아니라 여러 클라 응답하려면 멀티프로세스나 멀티쓰레딩 필요

#define BUF_SIZE 1024
void error_handling(char *message);

int main(int argc, char *argv[])
{
	int serv_sock, clnt_sock;
	char message[BUF_SIZE];
	int str_len, i;

	struct sockaddr_in serv_adr, clnt_adr;
	socklen_t clnt_adr_sz;

	if(argc!=2) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
	if(serv_sock == -1)
		error_handling("socket() error");

	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));

	if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)
		error_handling("bind() error");

	if(listen(serv_sock, 5) == -1)
		error_handling("listen() error");

	clnt_adr_sz = sizeof(clnt_adr);

	for(i=0; i<5; i++)
	{
		clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
		if(clnt_sock==-1)
			error_handling("accept() error");
		else
			printf("Connected clinet %d \n", i+1);

		while((str_len=read(clnt_sock, message, BUF_SIZE)) != 0)
			write(clnt_sock, message, str_len);

		close(clnt_sock);
	}
	close(serv_sock);
	return 0;
}

echo_server.c

#define BUF_SIZE 1024
void error_handling(char *message);

int main(int argc, char *argv[])
{
	int sock;
	char message[BUF_SIZE];
	int str_len;
	struct sockaddr_in serv_adr;

	if(argc!=3) {
		printf("Usage : %s <IP> <port>\n", argv[0]);
		exit(1);
	}

	sock = socket(PF_INET, SOCK_STREAM, 0);
	if(sock == -1)
		error_handling("socket() error");

	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
	serv_adr.sin_port=htons(atoi(argv[2]));

	if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
		error_handling("connect() error!");
	else
		puts("Connected.....");

	while(1)
	{
		fputs("Input message(Q to quit): ", stdout);
		fgets(message, BUF_SIZE, stdin);

		if(!strcmp(message, "q\n") || !strcmp(message,"Q\n"))
			break;

		write(sock, message, strlen(message));
		str_len=read(sock, message, BUF_SIZE-1);
		message[str_len]=0;
		printf("Message from server : %s", message);
	}
	close(sock);
	return 0;
}

echo_client.c

현재 문제점

  • 문자열이 나눠서 오지 않는다고 가정함
  • 지금은 문자열 작아서 오류 일어나지 않은거


📖 코딩 인터뷰 완전 분석


p.2 ~ 38



profile
너 정말 **핵심**을 찔렀어

0개의 댓글