echo_server.c
#include<stdio.h>
#include<unistd.h> //pid_t,socklen_t,read,write,close etc...
#include<sys/socket.h> //socket,accept,bind,listen, etc...
#include<stdlib.h>
#include<arpa/inet.h> //INADDR_ANY,sockaddr_in
#include<string.h>
int main(int argc,char *argv[])
{
struct sockaddr_in serv_adr,clnt_adr;
int sock_ser,sock_clnt;
char buf[100];
pid_t pid;
socklen_t adr_sz,len;
sock_ser = socket(PF_INET,SOCK_STREAM,0);
memset(&serv_adr,0,sizeof(serv_adr)); //소켓구조체 초기화
serv_adr.sin_family=AF_INET; //서버소켓의 주소체계 결정
serv_adr.sin_port = htons(atoi(argv[1])); //서버포트 결정
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); //서버의 아이피로는 가지고 있는 아이피중 임의의 하나로 설정한다는 뜻.
if(bind(sock_ser,(struct sockaddr *)&serv_adr,sizeof(serv_adr))==-1)
//생성한 소켓에 ip,port,주소체계를 설정해준다.
printf("bind() error\n");
if(listen(sock_ser,5)==-1) //서버에 연결가능도록 해줌.
printf("listen error\n");
while(1){
adr_sz = sizeof(clnt_adr);
sock_clnt = accept(sock_ser,(struct sockaddr*)&clnt_adr,&adr_sz);//클라이언트의 접속허용
if(sock_clnt== -1){ //접속이 없다면 아무런 일도 하지않는다.
}
else{ //접속이 들어온다면,
printf("accept !!\n");
pid=fork(); //자식프로세스를 생성한 후에,
if(pid==0){ //서버소켓의 파일디스크립터를 닫고,
close(sock_ser);
while((len=read(sock_clnt,buf,100))!=0) //데이터를 읽어들이고,
write(sock_clnt,buf,len); //다시클라이언트에게 보내준다.
close(sock_clnt); //클라이언트 소켓을 소멸시킴.
printf("disconnected socket...\n");
}
else close(sock_clnt); //부모프로세스는 클라이언트의 디스크립터를 닫는다.
}
}
close(sock_ser); //서버 소켓 소멸.
return 0;
}
echo_client.c
#include<stdio.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
int main(int argc,char *argv[])
{
int sock_clin;
struct sockaddr_in serv_adr,clnt_adr;
socklen_t len;
char buf[100];
sock_clin=socket(PF_INET,SOCK_STREAM,0); //소켓 생성과 필요한정보할당.
memset(&clnt_adr,0,sizeof(clnt_adr));
clnt_adr.sin_family=AF_INET;
clnt_adr.sin_addr.s_addr=inet_addr(argv[1]);
clnt_adr.sin_port=htons(atoi(argv[2]));
if(connect(sock_clin,(struct sockaddr *)&clnt_adr,sizeof(clnt_adr))==-1)
//소켓에 적혀있는 아이피와 포트번호를 보고 접속을 시도함.
printf("connected error\n");
printf("Connected!!...\n");
while(1){
if((strcmp(buf,"q\n"))==0 || (strcmp(buf,"Q\n")==0)) //q,Q를 입력하면 종료됨.
break;
printf("Input Message : ");
fgets(buf,100,stdin); //문자열을 입력받고,
write(sock_clin,buf,sizeof(buf)); //서버에 데이터를 전송,
read(sock_clin,buf,100); //read를 호출하면, 서버로 부터 데이터를 읽어들일 때까지 기다리다가 다음 명령어가 실행되므로, write바로 다음에 read를 쓴다고 해서 서버로부터 응답이 늦게온다고 데이터를 받지 못하는 현상은 일어나지 않는다.
printf("Message From server : %s\n",buf); //출력.
}
close(sock_clin); //소켓 소멸.
return 0;
}