Multi Process Echo Server
클라이언트의 서비스 요청(연결요청)이 있을 때마다 에코 서버는 자식 프로세스를 생성해서 서비스를 제공
1. accept 함수호출을 통해서 연결요청을 수락
2. 이때 얻게 되는 연결 소켓의 디스크립터를 자식 프로세스 생성 후 전달
3. 자식 프로세스는 전달받은 연결 디스크립터를 바탕으로 서비스를 제공
Multi Process Echo Client
기존 에코 서버는 클라이언트는 서버로 데이터를 전송 후 에코되어 돌아올 때까지 대기
== 에코되어 돌아온 데이터를 수신 후, 추가 전송 가능
서버로부터 수신 여부에 상관 없이 데이터 전송
클라이언트의 부모 프로세스 : 수신 담당
클라이언트이 자식 프로세스 : 송신 담당
데이터의 수신여부에 상관없이 데이터 전송이 가능
== 연속 데이터 전송이 가능
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 30
void error_handling(char *message);
void read_routine(int sock, char *buf);
void write_routine(int sock, char *buf);
int main(int argc, char *argv[])
{
int sock;
pid_t pid;
char buf[BUF_SIZE];
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);
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!");
pid=fork();
if(pid==0)
write_routine(sock, buf);
else
read_routine(sock, buf);
close(sock);
return 0;
}
void read_routine(int sock, char *buf)
{
while(1)
{
int str_len=read(sock, buf, BUF_SIZE);
if(str_len==0)
return;
buf[str_len]=0;
printf("Message from server: %s", buf);
}
}
void write_routine(int sock, char *buf)
{
while(1)
{
fgets(buf, BUF_SIZE, stdin);
if(!strcmp(buf,"q\n") || !strcmp(buf,"Q\n"))
{
shutdown(sock, SHUT_WR);
return;
}
write(sock, buf, strlen(buf));
}
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}