2009-05-21 2 views
1

유닉스 도메인 소켓을 통해 데이터를 공유하는 두 개의 간단한 프로그램을 설정했습니다. 하나의 프로그램은 Queue에서 데이터를 읽어서 다른 응용 프로그램으로 보냅니다. 전송되기 전에 각 데이터 조각은 길이가 4 바이트 앞에 붙습니다. 4 바이트보다 작 으면 왼쪽 위에있는 바이트는 '^'기호입니다.유닉스 도메인 스트림 소켓 더 많은 데이터를 보내야합니다.

클라이언트 응용 프로그램은 처음 네 바이트를 읽고 버퍼를 적절한 크기로 설정 한 다음 나머지를 읽습니다. 내가 가지고있는 문제는 처음 메시지를 완벽하게 보냈다는 것입니다. 그 후 다른 시간에 여분의 데이터가 전송되므로 "좋은 하루를 보낸다"와 같은 메시지가 "좋은 하루를 보낸다"라는 메시지가 나옵니다. 그래서 버퍼가 정확하게 지워지지 않는 것처럼 느껴지지만 그것을 찾지 못하는 것 같습니다.

클라이언트 코드 :

listen(sock, 5); 
for (;;) 
{ 
    msgsock = accept(sock, 0, 0); 
    if (msgsock == -1) 
     perror("accept"); 
    else do 
    { 
     char buf[4]; 
     bzero(buf, sizeof(buf)); 
     if ((rval = read(msgsock, buf, 4)) < 0) 
     perror("reading stream message"); 

     printf("--!%s\n", buf); 

     string temp = buf; 
     int pos = temp.find("^"); 
     if(pos != string::npos) 
     { 
      temp = temp.substr(0, pos); 
     } 

     int sizeOfString = atoi(temp.c_str()); 
     cout << "TEMP STRING: " << temp << endl; 
     cout << "LENGTH " << sizeOfString << endl; 
     char feedWord[sizeOfString]; 
     bzero(feedWord, sizeof(feedWord)); 

     if ((rval = read(msgsock, feedWord, sizeOfString)) < 0) 
       perror("reading stream message"); 

      else if (rval == 0) 
       printf("Ending connection\n"); 
      else 
       printf("-->%s\n", feedWord); 
       bzero(feedWord, sizeof(feedWord)); 
       sizeOfString = 0; 
       temp.clear(); 
     } 
     while (rval > 0); 
     close(msgsock); 
    } 
    close(sock); 
    unlink(NAME); 

서버 코드

   pthread_mutex_lock(&mylock); 
       string s; 
       s.clear(); 
       s = dataQueue.front(); 
       dataQueue.pop(); 
       pthread_mutex_unlock(&mylock); 

       int sizeOfString = strlen(s.c_str()); 
       char sizeofStringBuffer[10]; 

       sprintf(sizeofStringBuffer, "%i", sizeOfString); 
       string actualString = sizeofStringBuffer; 
       int tempSize = strlen(sizeofStringBuffer); 

       int remainder = 4 - tempSize; 
       int x; 
       for(x =0; x < remainder; x++) 
       { 
        actualString = actualString + "^"; 
       } 

       cout << "LENGTH OF ACTUAL STRING: " << sizeOfString << endl; 

       actualString = actualString + s; 

       cout << "************************" << actualString << endl; 
       int length = strlen(actualString.c_str()); 

       char finalString[length]; 
       bzero(finalString, sizeof(finalString)); 
       strcpy(finalString, actualString.c_str()); 

          if (write(sock, finalString, length) < 0) 
          perror("writing on stream socket");  

답변

2

오히려 '^'로 패킷 길이를 패딩보다는, 당신은 일을 떨어져 훨씬 좋을 것 :

snprintf(sizeofStringBuffer, 5, "%04d", sizeOfString); 

값이 0으로 채워지도록하십시오. 그러면 수신기에서 '^'문자를 파싱 할 필요가 없습니다. 코드.

디버그 코드도 편집하십시오. 현재 코드에 write()이 하나뿐입니다. 프로토콜 설명과 일치하지 않습니다.

이상적으로는 송신 루틴을 자체 기능으로 분리하십시오. writev()을 사용하여 "길이"필드를 포함하는 문자열을 실제 데이터를 보유하는 버퍼와 병합 한 다음이를 단일 원자 write()으로 전송하여 처리 할 수도 있습니다.

테스트되지 않은 코드는 다음과 같습니다

int write_message(int s, std::string msg) 
{ 
    struct iovec iov[2]; 
    char hdr[5]; 

    char *cmsg = msg.c_str(); 
    int len = msg.length(); 

    snprintf(hdr, 5, "%04d", len); // nb: assumes len <= 9999; 

    iov[0].iov_base = hdr; 
    iov[0].iov_len = 4; 

    iov[1].iov_base = cmsg; 
    iov[1].iov_len = len; 

    return writev(s, iov, 2); 
} 
+0

이것은 나에게 좋은 해결책 인 것처럼 보이지만 나는 readv로 무엇을해야하는지 혼동합니다. 독서면에서 iov [0]의 크기로 버퍼를 설정합니다.iov_len 그리고 그 버퍼를 iov [1] .iov_base로 채 웁니다. 이 경우에 – whatWhat

+0

은 readv를 사용할 수 없습니다. 먼저 4 바이트 길이 필드를 읽고 지정된 길이의 두 번째 버퍼를 읽어야합니다. – Alnitak

+0

여전히 문제의 코드에 근본적인 문제를 수정하지 않습니다. 즉, 읽을 문자열이 null로 끝나지 않아 printf()가 문자열을 출력하고 일부 스택은 첫 번째 null까지 인쇄합니다 발생했습니다. – Beano

2

당신은 모두 writeread의 반환 값을 확인해야 할뿐만 아니라 (미만 요청) -1뿐만 짧게/읽기 씁니다. perror으로 오류를 인쇄 한 후에도 계속 진행하는 것 같습니다. exit(2) 또는 그 밖의 작업을 수행하십시오.

0

두 가지 :

먼저 - 서버 측에서 당신은 당신의 배열의 끝을 쓰고있다.

char finalString[length]; 
bzero(finalString, sizeof(finalString)); 
strcpy(finalString, actualString.c_str()); 

strcpy()는 (null 종결을 끌어 문자) finalStringlength+1 문자를 복사합니다.

두 번째 (대부분 문제가 될 수 있음) - 클라이언트 측에서 읽은 문자열을 null로 끝내지 않으므로 printf()이 문자열을 인쇄 한 다음 해당 점까지 스택에있는 내용을 인쇄합니다 null을 명중한다.

두 버퍼를 모두 늘리면 모양이 좋아집니다.

관련 문제