访问套接字的文件描述符

时间:2012-05-28 20:47:37

标签: c sockets

这是包含在每个线程有一个客户端的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);

1 个答案:

答案 0 :(得分:2)

MySocket::sd是您需要与select()一起使用的描述符。 socket()accept()都返回可与select()一起使用的套接字描述符。更改tcp_passive_open()以返回MySocket*而不是Socket,然后您的主服务器线程将有权访问服务器的套接字描述符以传递给select()以检测传入连接,例如:

#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()在服务器套接字上报告挂起的入站连接连接时,调用accept()接受连接并获取其套接字描述符,然后您可以为其分配单独的MySocket它:

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

然后,您可以为MySocket创建一个新线程,该线程可以根据需要调用select()来检测该连接上的入站数据。