问题
I'm currently doing a school project for making http server. This server should be implemented by multiplexing, but socket programming is totally new area for me. So I made simple server to understand better of server but it doesn't work as I intended...
int main()
{
int server_socket, new_socket;
struct sockaddr_in server_address, new_address;
socklen_t new_len = sizeof(new_address);
const char *hello = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello world!"; // simple respond to client
// make server socket
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// turn server socket into non block fd
fcntl(server_socket, F_SETFL, O_NONBLOCK);
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_ZERO(&temp_set);
FD_SET(server_socket, &temp_set);
int fd_max = server_socket;
// bind address to server_socket and listen
bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address);
listen(server_socket, 1000);
// setting fd_set variable for select()
fd_set read_set, write_set, temp_set;
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_ZERO(&temp_set);
// add server_socket into temp_set
FD_SET(server_socket, &temp_set);
// set container for having all the fds
std::set<int> curfds, tmpfds;
tmpfds.insert(server_socket);
int fd_max = server_socket;
// start server
while(1) {
curfds = tmpfds;
fd_max = *curfds.rbegin();
read_set = temp_set;
write_set = temp_set;
// setting timedelay 0
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
select(fd_max + 1, &read_set, &write_set, NULL, &timeout);
// check which fd is activated
for (std::set<int>::iterator it = curfds.begin(); it != curfds.end(); ++it)
{
if (FD_ISSET(*it, &read_set) > 0)
{
// if server_socket is updated
if (*it == server_socket)
{
// accept client connection
new_socket = accept(*it, (sockaddr *)&new_address, &new_len);
// turn new_socket into non block
fcntl(new_socket, F_SETFL, O_NONBLOCK);
// update temp_set and tmpfds
FD_SET(new_socket, &temp_set);
tmpfds.insert(new_socket);
printf("client connected\n");
}
else // client socket
{
printf("ready to read from client\n");
char buff[1001];
int res = read(*it, buff, 1000);
buff[res] = 0;
// if i finished to read all http request
if (res == 0)
{
// check client is ready to be written
if (FD_ISSET(*it, &write_set) > 0) {
write(*it, hello, strlen(hello));
}
// deconnect
FD_CLR(*it, &temp_set);
close(*it);
tmpfds.erase(*it);
}
}
}
}
// for debugging loop
sleep(1);
printf("finished one rotation\n");
} // while
close(server_socket);
return 0;
}
I omitted checking error (checking return -1 every time by calling function select(), write(), read(), etc...) on purpose in this code for making easy to read.
And this is result.
finished one rotation
finished one rotation
finished one rotation
finished one rotation
finished one rotation
finished one rotation
client connected // <-- client connected
finished one rotation
client connected // <-- client connected again ??
ready to read from client
finished one rotation
...
problem 1. When I tried to "one time" connect from web browser, It shows two times connection message. Moreover, second connection happened after first select(). Why select() didn't update server_socket after accept() ??
problem 2. I can't send http response to client. It shows message "ready to read from client" but my web browser wait for server response infinitely....
Could you please explain me what happen on my server ? Thanks in advance.
来源:https://stackoverflow.com/questions/61965186/multiplexing-server-with-select-accept-happening-two-times