Hi,
I made some tests with passing sockets to the threads and there's a problem with the following code.
First, here's the client who's connecting to the server. It sends 1000 times a number to the server, everything works fine.
Code:
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
int main(int argc, char* argv[])
{
const int PORT = 10000;
struct sockaddr_in socketAddress;
int socketFd = socket(AF_INET, SOCK_STREAM, 0);
socketAddress.sin_family = AF_INET;
hostent* he = gethostbyname("localhost");
socketAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
socketAddress.sin_port = htons(PORT);
socklen_t addressLen = sizeof(socketAddress);
int res = connect(socketFd, (struct sockaddr*)&socketAddress, addressLen);
if (res == -1)
perror("connect");
for (int i = 1; i <= 1000; i++)
{
int no;
write(socketFd, &i, sizeof(int));
read(socketFd, &no, sizeof(int));
printf("read: %d\n", no);
}
close(socketFd);
}
Here's the server who's accepting connections and responses by incrementing received number by one:
Code:
#include <pthread.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
using namespace std;
void* run(void* params)
{
int* fd = (int*)params;
int no;
read(*fd, &no, sizeof(int));
printf("read: %d\n", no);
no++;
write(*fd, &no, sizeof(int));
return NULL;
}
int main()
{
const int PORT = 10000;
int serverFd = socket(PF_INET, SOCK_STREAM, 0);
int yes = 1;
setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
memset(&(serverAddress.sin_zero), '\0', 8);
bind(serverFd, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr));
listen(serverFd, 5);
fd_set readFds, testFds;
FD_ZERO(&readFds);
FD_SET(serverFd, &readFds);
while (true)
{
vector<pthread_t> fds;
fds.clear();
testFds = readFds;
int res = select(FD_SETSIZE, &testFds, (fd_set*)0, (fd_set*)0, (struct timeval*)0);
if (res < 1)
{
perror("select()");
exit(1);
}
for (int fd = 0; fd < FD_SETSIZE; fd++)
if (FD_ISSET(fd, &testFds))
{
if (fd == serverFd)
{
struct sockaddr_in clientAddress;
socklen_t clientLen = sizeof(clientAddress);
int clientFd = accept(serverFd, (struct sockaddr*)&clientAddress, &clientLen);
FD_SET(clientFd, &readFds);
}
else
{
int nread;
ioctl(fd, FIONREAD, &nread);
if (nread == 0)
{
close(fd);
FD_CLR(fd, &readFds);
}
else
{
/*
pthread_t th;
pthread_create(&th, NULL, &run, &fd);
fds.push_back(th);
*/
run(&fd);
}
}
}
cout << "fds.size()=" << fds.size() << endl;
// for (int i = 0; i < fds.size(); i++)
// pthread_join(fds[i], NULL);
}
}
The problem is following: server works fine if it calls run() and passes the socket file descriptor to it. But if I try to make threads to start run() and join them later, then it works for some time and it stops (receives few numbers or few hundreds but never receives them all). Those lines in code are commented out, if they are enabled, server creates threads for run().
What is the reason of such behaviour? Are threads created too quickly?