Recent Posts
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- PytestPluginManager
- 자원부족
- vfr video
- 코루틴 빌더
- 달인막창
- JanusWebRTC
- tolerated
- JanusGateway
- 깡돼후
- mp4fpsmod
- JanusWebRTCServer
- terminal
- 코루틴 컨텍스트
- table not found
- 오블완
- 개성국밥
- Spring Batch
- kotlin
- addhooks
- preemption #
- taint
- python
- JanusWebRTCGateway
- VARCHAR (1)
- pytest
- 헥사고날아키텍처 #육각형아키텍처 #유스케이스
- Value too long for column
- PersistenceContext
- 겨울 부산
- 티스토리챌린지
Archives
너와 나의 스토리
[CH.4-2,3] TCP기반 서버, 클리이언트의 구현 - Iterative 기반으로 구현 본문
반응형
TCP 서버의 기본적인 함수 호출 순서
listen() 함수를 호출하면 연결 요청이 가능한 상태가 된다.
이 listen() 함수의 호출이 의미하는 바를 알아보자
연결 요청 대기 상태로의 진입
- 연결 요청도 일종의 데이터 전송이다. 따라서 연결 요청을 받아들이기 위해서는 하나의 소켓이 필요하다.
- 이 소켓을 가리켜 서버 소켓 또는 리스닝 소켓이라고 한다.
- listen 함수의 호출은 소켓을 리스닝 소켓이 되게 한다.
클라이언트의 연결 요청 수락
- 연결 요청 정보를 참조하여 클라이언트 소켓과의 통신을 위한 별도의 소켓을 추가로 하나 더 생성한다.
- 이렇게 생성된 소켓을 대상으로 데이터의 송수신이 진행된다.
TCP 클라이언트의 기본적인 함수호출 순서
connect() 함수 호출할 때 연결할 서버의 주소 정보도 함께 전달
TCP 기반 서버, 클라이언트의 함수 호출 관계
서버의 listen() 함수 이후에야 클라이언트의 connect() 함수 호출이 유효하다.
-> listen()을 해야지만 연결 요청을 받을 수 있는 상태가 되기 때문
Iterative 서버의 구현
iterative 서버 코드
//iterative_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#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;
struct sockaddr_in clnt_adr;
//sockaddr_in은 IPv4 뒤에 8비트를 0으로 쉽게 넣기 위해 사용하는 것
socklen_t clnt_adr_sz;
if (argc != 2) { // port번호 길이가 2이여야한다.
printf("Usage : $s <port>\n", argv[0]);
exit(1);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0); // 다른 호스트와 통신하며, tcp 프로토콜을 사용한다.
if (serv_sock == -1)
error_handling("socket() error");
memset(&serv_adr, 0, sizeof(serv_adr)); // 뒤에 8바이트는 안써서 0으로 초기화 해주기 위해
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_adr.sin_port = htons(atoi(argv[1])); // 이렇게 하면 자신의 IP가 들어감
// 여기까지가 정보 초기화
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++)
{ // 5번의 연결을 받겠다.
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); //서버와 통신할 소켓
if (clnt_sock == -1)
error_handling("accept() error");
else
printf("Connected client %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;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
iterative 클라이언트 코드
// iterative_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#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); // fputs, fgets 찾아보기
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;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
실행 해보기
1. 서버 실행
2. 클라이언트1 실행
서버한테 메시지 보내면 서버가 답장
현재 서버 상황
2. 클라이언트 5개가 연결 요청 보냄
첫 번째 클라이언트는 연결이 되어 서버로부터 답신이 오고, 나머지 4개의 클라이언트는 대기 상태가 된다.
3. 첫 번째 클라이언트가 연결을 끊으면
기다리던 두 번째 클라이언트가 연결이 된다.
출처: [열혈 TCP/IP 소켓 프로그래밍]
반응형
'Computer Networks > 실습' 카테고리의 다른 글
[TCP/IP 소켓] Signal 함수, 핸들링, 좀비 프로세스 소멸, 다중접속 서버 (0) | 2019.11.08 |
---|---|
주소 할당 에러의 원인 - Time wait과 SO_REUSEADDR 옵션 (0) | 2019.11.08 |
[CH.4-1] TCP와 UDP에 대한 이해 (0) | 2019.10.09 |
[실습] 주소체계와 데이터 정렬 - IP주소/PORT번호/주소정보 표현/인터넷 주소(Internet Address) (0) | 2019.09.25 |
리눅스 기반 파일 조작하기 (0) | 2019.09.25 |
Comments