리눅스 멀티프로세스 소켓 프로그래밍에 대한 질문입니다
글쓴이: ShaYEL / 작성시간: 금, 2014/01/31 - 11:35오후
에코 클라이언트 프로그램인데요, 자식 프로세스를 만들어서 부모는 수신, 자식은 송신을 담당하도록 만들었습니다. 아래에 코드 전문을 적어놨는데요, 보내는 문자열이 짧을때는 문제가 없는데 문자열이 길어지면 조금 이상하게 작동합니다.
부모 프로세스와 자식 프로세스가 동시에 실행되는것처럼 보인다.. 는건 알겠는데 아래와 같은 경우 정확히 부모 프로세스가 어디까지 실행되고 나서 대기를 하고, 다음 자식 프로세스가 어디까지 실행되고 나서 대기를 하게 되는지, 이런것들이 이해가 잘 안됩니다.
if (pid == 0) write_routine(sock,buf); else read_routine(sock,buf);
이 부분이 정확히 어떤 과정으로 돌아가게 되는 건지 설명해 주시면 감사하겠습니다.
#include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFSIZE 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[BUFSIZE]; struct sockaddr_in serv_addr; if (argc != 3) { printf("Usage : ./%s [IP] [Port] \n",argv[0]); exit(1); } sock = socket(PF_INET,SOCK_STREAM,0); if (sock < 0) error_handling("socket() error"); memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(argv[1]); serv_addr.sin_port = htons(atoi(argv[2])); if (connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) error_handling("connect() error"); else printf("Connected....................\n"); 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) { int recv_len; while (1) { recv_len = read(sock,buf,BUFSIZE-1); if (recv_len == 0) return; else printf("Message from server: "); while (recv_len == BUFSIZE-1) { printf("%s",buf); recv_len = read(sock,buf,BUFSIZE-1); } buf[recv_len-1] = 0; printf("%s\n",buf); } } void write_routine(int sock, char *buf) { while (1) { fgets(buf,BUFSIZE-1,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); }
Forums:
올려놓고 보니... 주석이라도 달아서 올릴걸 그랬나요
올려놓고 보니... 주석이라도 달아서 올릴걸 그랬나요 orz
...
(1) read는 (당연한 얘기지만) 데이터를 읽은 다음 끝에 널문자('\0')를 붙여주지 않습니다. buf는 main의 로컬 변수니 초기화가 안 되어 있죠. read_routine에서 29자를 읽은 다음 printf를 하게 되면 무슨 일이 일어날지 모릅니다.
(2) 소켓 통신은 스트림 방식이라서, 보내는 쪽이 한번에 보냈다고 받는 쪽이 한번에 받는다는 보장이 안됩니다. 예를 들어 2000바이트를 보낸다면 커널에서 임의로 1000바이트짜리 두 개로 끊어서 보낼 수 있습니다.
그러면 읽는 쪽에서 29바이트씩 끊어 읽으면 중간에 한번 잘리게 되겠죠.
소켓을 읽는 코드는 read가 한번에 한 바이트씩 돌려줘도 동작할 수 있게 짜야 합니다.
댓글 달기