2012-08-02 2 views
-1

이미 백그라운드에서 내 서버를 실행하려고하는데 ps 아래에 표시되는 경우 내 서버가 실행되는 것을 볼 수 있지만 클라이언트를 실행하려고하면 올바른 서버가 " 서버에 성공적으로 연결되었습니다 "하지만 아무 것도 출력되지 않습니다.내 서버가 내 클라이언트에게 아무 것도 보내지 않는 이유

내 서버 코드

#include <iostream> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/un.h> 
#include <sys/types.h> 
#include <sys/socket.h> 

#ifndef AF_LOCAL 
#define AF_LOCAL AF_UNIX 
#endif 
#ifndef PF_LOCAL 
#define PF_LOCAL PF_UNIX 
#endif 

using namespace std; 

int main() 
{ 

int serverFd; 
int clientFd; 
int serverLen; 
int clientLen; 
string message; 
string serverSockAddrPtr; 
struct sockaddr* serverSockAddressPnt; 
struct sockaddr* clientSockAddressPnt; 
struct sockaddr_un serverAddress; 
struct sockaddr_un clientAddress; 

cout << "" << endl; 
cout << "Running server program 'css' ...... " << endl; 
cout << "" << endl; 


// SOCKET CREATION PART - SERVER 
serverFd = socket (AF_LOCAL, SOCK_STREAM, 0); 

/* Set domain type */ 
serverAddress.sun_family = AF_LOCAL; 

/* Set name */ 
strcpy (serverAddress.sun_path, "CServer"); 


/* GET SIZE OF Server Addres */ 
serverLen = sizeof serverAddress; 
/* GET SIZE OF Client Addres */ 
clientLen = sizeof clientAddress; 

/* Get Server Sock Address Pointer*/ 
serverSockAddressPnt = (struct sockaddr *) &serverAddress; 
/* Get Client Sock Address Pointer*/ 
clientSockAddressPnt = (struct sockaddr *) &clientAddress; 

/* Create file */ 
bind (serverFd, serverSockAddressPnt , serverLen); 

/* listen for connection */ 
listen (serverFd,5); 


cout << "" << endl; 
// SOCKET CREATION END - SERVER 


while(1) 
{ 
//accept client connection 
clientFd = accept(serverFd, clientSockAddressPnt, (socklen_t*)&clientLen); 

if(clientFd >= 0) 
{ 
    if(fork() == 0) 
    { 
     message="Successfully connected to the server"; 
     write(clientFd,message.c_str(),strlen(message.c_str())+1); 
     close(clientFd); 
     exit(0); 
    } 
    else 
     close(clientFd); 
} 

} 

return 0; 
} 

내 클라이언트 코드

#include <iostream> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/un.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#define DEFAULT_PROTOCOL 0 
#ifndef AF_LOCAL 
#define AF_LOCAL AF_UNIX 
#endif 
#ifndef PF_LOCAL 
#define PF_LOCAL PF_UNIX 
#endif 

using namespace std; 

/* READ LINE FUNCTION*/ 
int readLine (int fd,char* str) 
{ 
    int n; 
    do 
    { 
     n = read(fd,str,1); 
    }while(n>0&& *str++ != 0); 
    return(n>0); 
} 
/* READ LINE FUNCTION END*/ 


/* READ SERVER FUNCTION*/ 
void readServer (int fd) 
{ 
    char str[500]; 
    while (readLine(fd,str)) 
    { 
     printf("%s",str); 
    } 
} 
/* READ SERVER FUNCTION END*/ 




int main() 
{ 

int clientFd,serverLen,result; 
struct sockaddr_un serverAddress; 
struct sockaddr* serverSockAddressPnt; 

/* Get Server Sock Address Pointer*/ 
serverSockAddressPnt = (struct sockaddr *) &serverAddress; 

/* GET SIZE OF Server Addres */ 
serverLen = sizeof serverAddress; 

clientFd = socket (AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL); 
serverAddress.sun_family = AF_LOCAL; 
strcpy (serverAddress.sun_path,"CServer"); 

do 
{ 
    // a loop to keep trying till connected. 
    result=connect(clientFd,serverSockAddressPnt,serverLen); 
    if(result==-1) 
    { 
     //wait for 1 second to retry 
     sleep(1); 
    } 

}while(result==-1); 
readServer (clientFd); 
close (clientFd); 
exit(0); 

return 0; 
} 
+1

서버 프로그램에 gdb를 첨부하고 진행 상황을 확인하십시오. – jman

+0

GDB에서 디버깅하는 것 외에도 서버 나 클라이언트 코드를 통해 스테핑을 수행하는 것 외에 더 많은 출력을 추가 할 수 있습니다. 예를 들어 클라이언트가 성공적으로 연결되면 클라이언트와 서버 모두에서 콘솔로 인쇄 할 수 있지만 더 중요한 것은 오류 코드와 함께 _fails_가있을 때 출력을 인쇄하는 것입니다. –

+1

이것은 C가 아니며 C와 C++가 혼합 된 것입니다. 그만한 가치가 없다는 것을하지 말고, 사용하고 싶은 언어를 결정하십시오. –

답변

0

클라이언트가 연결되는 서버 모른다. struct sockaddr* serverSockAddressPnt;하지만 에 대한 포인터는 serverSockAddressPnt으로 정의됩니다. 하지만 초기화 될 예정이거나 연결할 서버의 IP 주소가 할당되어 있어야합니다.

+0

OP는 '& serverAddress'에 포인터를 할당하여 제대로 초기화됩니다. –

1

serverAddress 변수가 초기화되지 않았습니다. 나는 이것을 확인하지 않았지만 가장 가능성이 높은 serverAddress.sun_pathchar에 대한 포인터이며, 임의의 값으로 초기화됩니다. 이

strcpy (serverAddress.sun_path,"CServer"); 

은 임의의 메모리를 덮어 씁니다.

  • 항상 그래 항상 모든 변수를 초기화 : C에서이 작업을 수행하는 올바른 방법은 일반적으로

    struct sockaddr_un serverAddress = { 0 }; 
    

    입니다. 그렇게하지 않을 경우 약간의 효율성 향상에 대해 걱정하지 마십시오. 그것은 대개 가치가 없으며 어떤 경우에는 아직 거기에 있지 않습니다. (여기에서 0으로 적절한 초기화를하면 프로그램이 처음부터 충돌을 일으킬 수 있습니다.)

  • 항상 모든 경고 옵션을 사용하여 컴파일하십시오.

  • C와 C++을 혼용하지 마십시오. 그럴 가치가없는 미묘한 차이점이 있습니다. 특히 여기서는 C++을 사용하여 아무 것도 얻지 못합니다.

+0

특히 "처음부터 멋지게 충돌"부분을 좋아합니다. –

+0

['sockaddr_un'] (http://linux.die.net/man/7/unix) 구조체를 살펴 봐야한다고 생각합니다. 'sun_path' 멤버는 적절한 배열입니다. –

1

p1. Joachim이 제안한 것처럼 오류 처리를 코드에 추가하십시오. 문제의 가장 큰 원인은 바인딩하는 것입니다. 그러나 그 전에 바인딩 된 (즉, "CServer") 소켓 파일 (실험중인 파일이므로 이미 존재한다고 가정)을 삭제하지 않습니다.

그래서 바인드가 실패하더라도 오류가 고온 처리되므로 서버가 시작됩니다 (ps 명령으로 볼 수 있음). ps를 사용하여 서버가 실행중인 것을 볼 수 있더라도 클라이언트는 연결할 수 없습니다. 그래서 바인드하기 전에 소켓 파일의 링크를 해제 (삭제)하면 해결할 수 있습니다.

unlink("CServer"); 
bind (serverFd, serverSockAddressPnt , serverLen); 

이 문제가 해결되기를 바랍니다.

내가 http://tkhanson.net/cgit.cgi/misc.git/plain/unixdomain/Unix_domain_sockets.html

또 다른 관찰 당신이 좀비 핸들러를 추가하지 않은 이후 코드는 좀비를 (리눅스에서 소멸 한 프로세스 ps 명령이 작동하지 않는 항목을 표시합니다) 생산한다는 것입니다 발견 튜토리얼에 대한 링크를 공유 .

일시적인 해결책은 제안하는 것이지요.SIGCHLD (자식 시그널의 죽음)를 무시하기 위해 서버 프로그램에서 소켓 호출 이전에 (Linux를 가정 할 때) 아래 줄을 추가하십시오 (signal.h 포함). 좀비는 보이지 않습니다.

signal(SIGCHLD, SIG_IGN); 
관련 문제