What you are trying to do:
Hello, I'm rewriting a old legacy custom http server used on a website.
What's the issue:
When accept is called, Can't accept client: bad file descriptor error will be outputted to the terminal even though code looks correct.
What you tried:
Code:
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
// This version of software is licensed under public domain feel free to use for any purpose
typedef struct{
char* http_path;
void (*function);
} location;
unsigned short server_count = 0;
/*
* typedef struct is bad practice especially by linux convention which i try to
* follow but for some reason program will compile or fail randomly and typedef
* struct fixes it for some reason
*/
typedef struct{
unsigned char running;
unsigned id;
unsigned locationCount;
location* locations;
unsigned port;
} http_server_t;
http_server_t* servers;
char nServer(unsigned short port) {
server_count++;
char status = server_count;
// The warning happens here can be disregarded
if(server_count == 1) {
status = (servers = malloc(sizeof(servers)*server_count));
}else{
status = (realloc(servers, sizeof(servers)*server_count));
}
if(!status){
return -1;
}
servers[server_count].port = port;
servers[server_count].running = 1;
servers[server_count].locations = sizeof(servers[server_count].locations)*servers[server_count].locationCount+1;
return server_count;
}
typedef struct __attribute__((packed)) {
unsigned sock;
struct sockaddr* addr;
struct sockaddr_in inf;
} serverHandlerData;
void serveClient() {
}
void socketHandle(void* data) {
// lazy to properly name these stuff
// FIXME: Refactor the code here
serverHandlerData *fixed = data;
unsigned sock = fixed->sock; struct sockaddr* addr = fixed->addr;
struct sockaddr_in in = fixed->inf;
if(bind(sock, (struct sockaddr *)&in, sizeof(struct sockaddr))) {
perror("Can't bind");
return;
}
if((listen(sock, 0)) < 0) {
perror("Can't listen the socket");
return;
}
for(;;) {
int csock;
struct sockaddr_in caddr;
if((csock = accept(csock, (struct sockaddr*)&caddr, (socklen_t)sizeof(struct sockaddr))) < 0) {
perror("Can't accept client");
return;
}
unsigned char* buffer = malloc(100);
read(csock, buffer, 100);
printf(buffer);
close(csock);
}
}
void iServers() {
for(unsigned long x = 1; x < server_count; x++) {
struct sockaddr_in addr;
unsigned char status = 0;
unsigned int sock = 0;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket can't be made due a error");
return;
}
printf("%d", servers[x].port);
memset(&addr, 0, sizeof(addr));
// ipv4
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(servers[x].port);
/*if((setsockopt(sock, (struct sockaddr*)&addr, SO_REUSEADDR,
SO_BROADCAST, (struct socklen_t*)sizeof(SO_BROADCAST))) < 0){
perror("Failure while setting socket options");
return;
} */
serverHandlerData s;
s.sock = sock;
s.addr = (struct sockaddr*)&addr;
s.inf = addr;
pthread_t serverHandle;
pthread_create(&serverHandle, NULL, socketHandle, &s);
pthread_join(serverHandle, NULL);
}
}
unsigned char running = 1;
void ctrlCHandler(){
running = 0;
}
int main() {
nServer(4080);
// FIXME: Second server never gets toggled on
nServer(1010);
//nServer(80);
iServers();
return 0;
}
Minimal example? I do not know what exactly triggers the error so I can't create a minimal reproducable example.
IMHO, the problem is that you have requested
listen(sock, 0); /* BAD */
as this sets the incoming backlog queue to 0 entries, dissalowing connection establishment. The normal call should be (to behave as it used to)
listen(sock, 5); /* OK */
that allows up to 5 connect requests before starting to reject connections.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.