Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Socket to Thread C

I'm trying to make a network system using UDP. I've managed to get it working, but now I want to put the listening part in a separate thread so I can continue with the program without having to wait for messages (it's going to be used for a game).

The problem is that when I pass the socket to the new thread and use it for listening it doesn't work and just receives random input constantly. When I use the exact same code in the method where I initialize the socket, everything works fine.

This works:

bool serverUDP() {
WSADATA w;
SOCKET sd;

struct sockaddr_in server, client;
char buffer[DEFAULT_BUFLEN];
int bytes_received;
int client_length;

/* Open windows connection */
if (WSAStartup(MAKEWORD(2,2)/*0x0101*/, &w) != 0) {
    fprintf(stderr, "Could not open Windows connection.\n");
    return false;
}

/* Open a datagram socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET) {
    fprintf(stderr, "Could not create socket.\n");
    WSACleanup();
    return false;
}

/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));

/* Set family and port */
server.sin_family = AF_INET;
server.sin_port = htons(atoi(DEFAULT_PORT));

server.sin_addr.S_un.S_un_b.s_b1 = 127;
server.sin_addr.S_un.S_un_b.s_b2 = 0;
server.sin_addr.S_un.S_un_b.s_b3 = 0;
server.sin_addr.S_un.S_un_b.s_b4 = 1;

/* Bind address to socket */
if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
    fprintf(stderr, "Could not bind name to socket.\n");
    closesocket(sd);
    WSACleanup();
    return false;
}

client_length = (int)sizeof(struct sockaddr_in);

/* Receive bytes from client */
while (true) {
    bytes_received = recvfrom(sd, buffer, DEFAULT_BUFLEN, 0, (struct sockaddr *)&client, &client_length);
    fprintf(stderr,"received: %s\n", buffer);
}

closesocket(sd);
WSACleanup();   

return true;
}

This doesn't:

bool serverUDP() {
WSADATA w;
SOCKET sd;

struct sockaddr_in server, client;
char buffer[DEFAULT_BUFLEN];
int bytes_received;
int client_length;

/* Open windows connection */
if (WSAStartup(MAKEWORD(2,2)/*0x0101*/, &w) != 0) {
    fprintf(stderr, "Could not open Windows connection.\n");
    return false;
}

/* Open a datagram socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET) {
    fprintf(stderr, "Could not create socket.\n");
    WSACleanup();
    return false;
}

/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));

/* Set family and port */
server.sin_family = AF_INET;
server.sin_port = htons(atoi(DEFAULT_PORT));

server.sin_addr.S_un.S_un_b.s_b1 = 127;
server.sin_addr.S_un.S_un_b.s_b2 = 0;
server.sin_addr.S_un.S_un_b.s_b3 = 0;
server.sin_addr.S_un.S_un_b.s_b4 = 1;

/* Bind address to socket */
if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
    fprintf(stderr, "Could not bind name to socket.\n");
    closesocket(sd);
    WSACleanup();
    return false;
}

_beginthread((void(*)(void*))receiveThread,0,(void *)sd);

closesocket(sd);
WSACleanup();   

return true;
}

void receiveThread(SOCKET sd)
{
struct sockaddr_in client, server;
char buffer[DEFAULT_BUFLEN];

int bytes_received;
int client_length;

client_length = (int)sizeof(struct sockaddr_in);

while (true) {
    bytes_received = recvfrom(sd, buffer, DEFAULT_BUFLEN, 0, (struct sockaddr *)&client, &client_length);
    fprintf(stderr,"received: %s\n", buffer);
}
}

The second piece of code just spams random input, as though it's constantly receiving some weird message. The, first piece of code waits for a message and continues when it gets one (I've got a client part too).

Thanks for your help!

Cheers,

Maxim Schoemaker

like image 364
Maxim Schoemaker Avatar asked Nov 23 '25 13:11

Maxim Schoemaker


1 Answers

The main thread closes the socket immediately after starting the other thread. Therefore the thread no longer has a valid socket handle.

like image 61
Mark Wilkins Avatar answered Nov 25 '25 03:11

Mark Wilkins