echo_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;

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 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);



echo_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);

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);




에코 클라이언트의 문제점

- 제대로 동작은 하나 문제의 발생 소지가 있는 TCP 에코 클라이언트의 코드

write(sock. message, strlen(message)); 

str_len = read(sock, message, BUF_SIZE=1);

message[str_len] = 0;

printf("Message from server: %s", message);


TCP의 데이터 송수신에는 경계가 존재하지 않는다! 그런데 위의 코드는 다음 사항을 가정하고 있다.

  "한 번의 read 함수 호출로 앞서 전송된 문자열 전체를 읽어 들일 수 있다."


그러나 이는 잘못된 가정이다. TCP에는 데이터의 경계가 존재하지 않기 때문에 서버가 전송한 문자열의 일부만 읽혀질 수도 있다.

'개발' 카테고리의 다른 글

해피해킹 딥스위치 설정  (0) 2016.12.05
Vi/Vim 단축키 모음  (0) 2016.12.02
vim 단축키 일람  (0) 2016.12.02
리눅스 - 파일 폴더 권한 바꾸기  (0) 2016.12.02
4.2. TCP기반 서버, 클라이언트의 구현  (0) 2016.12.01
블로그 이미지

잉비니

,