[Socket프로그래밍] toupper() 함수가 동작을 안하는 이유

gyxor의 이미지

      1 #include<unistd.h>
      2 #include<stdio.h>
      3 #include<ctype.h>
      4 #include<sys/types.h>
      5 #include<sys/socket.h>
      6 #include<netinet/in.h>
      7 
      8 #define SIZE sizeof(struct sockaddr_in)
      9 
     10 int newsocket;
     11 
     12 main()
     13 {
     14         int c;
     15         int sockfd;
     16         int newsockfd;
     17         struct sockaddr_in server = {AF_INET, 9001 , INADDR_ANY};
     18 
     19         sockfd = socket(AF_INET, SOCK_STREAM, 0);
     20         bind(sockfd, (struct sockaddr *) &server, SIZE );
     21         listen(sockfd, 5);
     22         while(1)
     23         {
     24                 if( (newsockfd = accept(sockfd, NULL, NULL)) == -1)
     25                 {
     26                         perror("accept call failed");
     27                         continue;
     28                 }
     29                 if( fork() == 0)
     30                 {
     31                         while(1)
     32                         {
     33                                 recv(newsockfd, &c, 1, 0);
     34                                 c = toupper(c);
     35                                 send(newsockfd, &c, 1, 0);
     36 
     37                         }
     38                 }
     39         }
     40         return 0;
     41 }

위는 Server 소스입니다.

      1 #include<ctype.h>
      2 #include<sys/types.h>
      3 #include<sys/socket.h>
      4 #include<netinet/in.h>
      5 
      6 #define SIZE sizeof(struct sockaddr_in)
      7 
      8 main()
      9 {
     10         char c,rc;
     11         int size;
     12         int sockfd;
     13         struct sockaddr_in server = {AF_INET, 9001};
     14         server.sin_addr.s_addr = inet_addr("x.x.x.x");
     15 
     16         sockfd = socket(AF_INET, SOCK_STREAM, 0);
     17         connect(sockfd, (struct sockaddr *)&server, SIZE);
     18         while(1)
     19         {
     20                 c = getchar();
     21                 send(sockfd, &c, 1, 0);
     22                 recv(sockfd, &rc, 1, 0);
     23                 printf("%c", rc);
     24         }
     25 }
     26 

위는 Client 소스입니다.
Client에서 Server로 char를 보내면 server에서는 이를 toupper함수를 돌린후 결과를 다시 Client로 보내주는 프로그램입니다.
실제로 에러없이 컴파일되는 소스입니다.

위 소스를 돌려보면 한가지 이상한점이 client에서 입력을 한 문자들이
소문자에서 대문자로 바뀌지 않은것을 볼 수 있습니다.

하지만 Server Source 14번째 줄에서 char c; 로 된것을
char c = 0;
으로 바꾸어주면 소문자-> 대문자 로 정상적으로 실행이 되는것을 볼 수 있습니다.
c라는 변수를 초기화 한것과 초기화 하지 않은 것이 왜 toupper함수를 동작하게 만드는 조건이 되는것인지 도무지 알 수가 없습니다.

소스를 돌려보기 귀찮으시겠지만
client의 14번째 줄에
server.sin_addr.s_addr = inet_addr("x.x.x.x");
아이피 부분만 채워넣으셔서 ..
한번 테스트 해보시면 정말 이상하다는것을 알게 되실 것입니다.
답변 부탁드립니다.

gyxor의 이미지

참고로 gcc 4.0에서 테스트 했을때는 저런 현상이 나타나지 않았습니다.
하지만 구버젼 gcc 3.2.3 에서는 저련 현상이 발생을 합니다. 버그로 봐야 하는것인가요?

채영구의 이미지

printf()에서 %c로 찍지말고 integer 값 전체를 찍어보세요.

익명사용자의 이미지

서버 쪽 소스에서 이게 좀 마음에 걸리네요.

14 int c;
33 recv(newsockfd, &c, 1, 0);
34 c = toupper(c);
35 send(newsockfd, &c, 1, 0);

int형의 크기는 1바이트가 아닌데 이러면 그중의 맨 앞에 있는 1바이트만 읽고 쓰게 되죠.

latex의 이미지

주고받는 데이터의 형식이나 크기에 아주 민감하기 때문에 지금 char를 주고 받는다면 최소한 casting은 필요 할 것을 생각됩니다. 위분이 이야기 한것 처럼 보내기 전에 형을 변경해서 시도 보고 결과를 일러 주시면,
저는 왜 못하냐면, 검증할 컴파일러도 없고, 에또 중국 출장이고 에또 귀찮기도 하고 새 주실분~
죄송합니다.
int main(int argc, char* argv[], char* arge[])
{
return 0;
}

int main(int argc, char* argv[], char* arge[])
{
return 0;
}

gyxor의 이미지

int 형으로 선언한것이 문제였군요;
초기화를 한 경우엔 정상수행이 된 것이 좀 이상하지만
casting을 안한것은 사실이므로 프로그래밍 실수로 봐야겠군요;
정말 답변감사드립니다.