2012-05-28 4 views
1

이것은 쓰레드 당 하나의 클라이언트를 가진 tcp 서버 - 클라이언트 메시지 서비스에 포함 된 .c 파일의 일부이다. 서버 스레드 내부에서 select를 사용하여 새로운 들어오는 연결이나 버퍼에 쓰여지는 데이터를 처리하고 싶지만 문제는 클라이언트와 서버의 소켓 파일 설명자를 필요로한다는 것입니다.소켓의 파일 디스크립터에 접근하기

코드의이 부분에서는 서버의 소켓 설명자가 s-> sd 안에 있지만이 함수 외부에서 (소켓)을 반환하기 때문에 액세스 할 수 있습니다.

어떻게해야합니까?

#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 

typedef struct { 
    int sd; //id of the socket?? 
    char *ip_addr; 
    int port; 
    } MySocket; 

Socket tcp_passive_open(int port) 
{                      
    MySocket *s = (MySocket *)malloc(sizeof(MySocket)); 
    struct sockaddr_in addr; 
    s->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL); 

    memset(&addr, 0, sizeof(struct sockaddr_in)); 
    addr.sin_family = PROTOCOLFAMILY; 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    addr.sin_port = htons(port); 

    if (bind(s->sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { 
    die("tcp_open_server failed(): bind() failed"); 
    } 

    s->port = port; 
    s->ip_addr = NULL; //INADDR_ANY ... 
    return (Socket)s; 
} 

주 (코드의 대부분은 그것을 읽을 수 있도록 생략) :

Socket server = tcp_passive_open(PORT); 
FD_SET(SOCKETDESCRIPTOR_SERVER??,&master_socketDescriptors); 
+0

s는 포인터입니다. 구조체를 반환하려고 시도합니다. 대신 포인터를 반환하십시오 (함수의 반환 유형을 변경해야 함). 그리고 (struct sockaddr *)를 제외한 모든 캐스트를 제거하십시오. 또한 Socket은 무엇입니까? MySocket이되어야합니까? – wildplasser

+0

bedankt wildplasser :) 문제는 내가 tcp_passive_open을 변경하지 않고 시도하고 싶지만 가능하지 않을 수도 있습니다. 그리고 socket은 파일 형식입니다. (struct no가 아니라) 생각합니다. 그래서 당신은 해결책이 아닙니다. 나는 두려워합니다. – Thomas

+0

왜 MySocket 형식의 typedeffed, malloc() ed 및 initialised 중 왜 Socket을 반환하려고합니까? 나 한테 이해가 안돼. (IANAB ;-) – wildplasser

답변

2

MySocket::sdselect()와 함께 사용하는 데 필요한 설명이다. socket()accept()select()과 함께 사용할 수있는 소켓 설명자를 반환합니다. 예를 들어, 다음 주 서버 스레드가 들어오는 연결을 검출 select()에 전달할 서버의 소켓 기술자에 액세스 할 수 있습니다하는 MySocket* 대신 Socket의를 반환하는 tcp_passive_open() 변경 :

#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 

typedef struct { 
    int sd; 
    char *ip_addr; 
    int port; 
} MySocket; 

MySocket* tcp_passive_open(int port) { 
    MySocket *s = (MySocket *)malloc(sizeof(MySocket)); 
    if (s == NULL) { 
     die("tcp_open_server failed(): malloc() failed"); 
    } 

    s->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL); 
    if (s->sd == -1) { 
     die("tcp_open_server failed(): socket() failed"); 
    } 

    struct sockaddr_in addr; 
    memset(&addr, 0, sizeof(struct sockaddr_in)); 
    addr.sin_family = PROTOCOLFAMILY; 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    addr.sin_port = htons(port); 

    if (bind(s->sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { 
     die("tcp_open_server failed(): bind() failed"); 
    } 

    s->port = port; 
    s->ip_addr = NULL; //INADDR_ANY ... 
    return s; 
} 

합니다. 이후

MySocket* server = tcp_passive_open(PORT); 
FD_SET(server->sd, &master_socketDescriptors); 

select() 보고서 서버 소켓에 보류중인 인바운드 연결 연결, 당신은 그것을위한 별도의 MySocket 할당 할 수있는 연결을 받아 소켓 기술자를 얻기 위해 accept() 전화 :

int sd = accept(server->sd, ...); 
if (sd != -1) { 
    MySocket *client = (MySocket*) malloc(sizeof(MySocket)); 
    client->sd = sd; 
    ... 
} 

그런 다음 MySocket에 대한 새 스레드를 만들 수 있으며 해당 스레드는 select()을 호출하여 필요에 따라 해당 연결의 인바운드 데이터를 감지 할 수 있습니다.

+0

thx; 필자는 tcp_passive_open을 보존하기를 원했는데, 그 이유는 필자가 액세스 권한을 가지고 있지 않기 때문입니다 (.h 파일에만 해당). "Socket server = tcp_passive_open (PORT);"을 기억하십시오. tcp_passive_open이 정의 된 파일의 .h 파일을 포함하는 다른 c 파일에 있습니다. 그러나 나는 그 안에 .h 파일 안에 선언이 있다는 것을 잊었다 : "typedef void * Socket;" 어쩌면이 소켓 설명자를 얻으려면 사용할 수 있습니까? – Thomas

+0

확인; 난 분명히이 소켓을 사용하여 MySocket 구조체로 reconverted 수 있습니다 해결 : \t 소켓 서버 = tcp_passive_open (포트); \t MySocket * s = (MySocket *) 서버; \t printf ("소켓 설명자 : % d", s-> sd); 왜 소켓으로 변환해야하는지 (또는 모든 함수가 MySocket 대신 소켓을 반환하는 이유) 모르겠지만 그 파일을 준 사람에게 물어볼 것입니다. 고맙습니다. – Thomas

+0

일반적인 캡슐화 방식입니다. 처음에 코드를 작성한 사람은 외부 코드에서 'MySocket'의 세부 사항을 숨기려고했습니다. 그래서'Socket'은 평범한'void * '포인터에 매핑됩니다. 그렇게하면 외부 코드에 영향을 미치지 않고 MySocket의 내용을 변경할 수 있습니다. 이 경우, 그 코드는'Socket'을 입력 받아 내부적으로 소켓 디스크립터를 처리하는'tcp_accept()'와'tcp_select()'함수를 노출시켜야합니다. 코드가 그러한 기능을 가지고 있지 않다면 아마도 저자의 부분에 대한 감독이나 실수 한 프로그래밍 일 것입니다. –