-
Sockets and threads
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?
-
> pthread_create(&th, NULL, &run, &fd);
You're passing a pointer to a local variable, which gets changed in between you creating the thread, and the new thread getting a chance to look at it with
int* fd = (int*)params;
-
-
I've been looking for code like this to pull apart for a bit, but when I try to compile the server It throws an error.
Code:
/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/cstdlib:135: error: ‘::system’ has not been declared
is there any reason why I'm getting this error? Is it the libraries I have installed? If so which should I be getting? I'm running Ubuntu 7.04 (feisty)
-
Code:
g++ client.cpp -o client
g++ server.cpp -o server -lpthread
compiles client and server. Beside standard library you need only thread library which is probably installed during Linux installation.