Reputation: 1706
This is part of a .c file that in included into a tcp server-client message service that has one client per thread; I want to use select inside the server thread to handle new incoming connections or data being written in a buffer but the problem I have is that I need the socket file descriptor to do that of the clients and of the server.
In this part of the code the socket descriptor of the server is inside s->sd but I can seem to access it outside this function because it returns (socket).
What can I do? (large parts of code are omitted to make it readable)
#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;
}
main:
Socket server = tcp_passive_open( PORT );
FD_SET(SOCKETDESCRIPTOR_SERVER??,&master_socketDescriptors);
Upvotes: 1
Views: 15440
Reputation: 597971
MySocket::sd
is the descriptor you need to use with select()
. Both socket()
and accept()
return socket descriptors that can be used with select()
. Change tcp_passive_open()
to return a MySocket*
instead of a Socket
, then your main server thread will have access to the server's socket descriptor to pass to select()
for detecting incoming connections, eg:
#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);
Afterwards, when select()
reports a pending inbound connection connection on the server socket, call accept()
to accept the connection and obtain its socket descriptor, then you can allocate a separate MySocket
for it:
int sd = accept(server->sd, ...);
if ( sd != -1 ) {
MySocket *client = (MySocket*) malloc(sizeof(MySocket));
client->sd = sd;
...
}
Then you can create a new thread for that MySocket
, and that thread can call select()
to detect inbound data on that connection as needed.
Upvotes: 2