Многопоточный TCP-сервер в C - PullRequest
       49

Многопоточный TCP-сервер в C

4 голосов
/ 23 февраля 2011
int sock, connected, bytes_received, true = 1;
struct sockaddr_in server_addr, client_addr;
int sin_size;

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("Socket");
    exit(1);
}

if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &true, sizeof (int)) == -1) {
    perror("Setsockopt");
    exit(1);
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[1]));
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero), 8);

if (bind(sock, (struct sockaddr *) &server_addr, sizeof (struct sockaddr))
        == -1) {
    perror("Unable to bind");
    exit(1);
}

if (listen(sock, 5) == -1) {
    perror("Listen");
    exit(1);
}

printf("\nTCPServer Waiting for client on port 5003");
fflush(stdout); 

while (1) 
{
    pthread_t *child = (pthread_t *)malloc( sizeof(pthread_t) );

    sin_size = sizeof (struct sockaddr_in);
    connected = accept(sock, (struct sockaddr *) &client_addr, &sin_size);
    printf("\n I got a connection from (%s , %d)\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    pthread_create(child, NULL, interpretMessage, NULL);
    free(child);
}

Мой TCP-сервер прослушивает порт 5003. Когда соединение установлено, я хочу создать поток и запустить функцию interpretMessage. У меня есть несколько вопросов по этому поводу ...

1) Я делаю вызов malloc и free в нужных местах?

2) После вызова pthread_create мой код сразу же переходит в "free (child)"; а затем вернуться к началу цикла while?

3) Что произойдет, если 5 человек подключатся одновременно (как код запускает 5 потоков?)

1 Ответ

6 голосов
/ 23 февраля 2011

Ваш код правильно использует malloc и free, но то, как вы это делаете, делает реализацию более сложной, чем необходимо. Функция pthread_create работает путем записи идентификатора нового потока в память, указанную его первым параметром. В вашем случае вы динамически распределяете этот буфер, а затем немедленно освобождаете его. Следовательно, память ограничена одной итерацией цикла while. Если это то, что вам нужно, вам, вероятно, лучше просто выделить pthread_t в стеке и передать указатель на него в pthread_create:

while (1) 
{
    pthread_t child;

    /* ... */

    pthread_create(&child, NULL, interpretMessage, NULL);
}

Теперь, когда child локально ограничен в цикле, управление памятью будет обрабатываться автоматически без необходимости вызова malloc или free.

Что касается вашего второго вопроса о том, продолжает ли элемент управления free (child) и затем возвращаться к вершине цикла после вызова pthread_create, да, это правильно. Будет создан второй поток под управлением interpretMessage, поэтому возможна некоторая задержка, если исходный процесс задерживается, но управление возобновляется с этой точки.

Что касается вашего последнего вопроса, если все пять человек подключаются одновременно, то в следующие пять раз, когда вы наберете accept, функция предоставит один сокет для следующего входящего соединения. То есть ОС автоматически ставит в очередь входящие соединения в некотором порядке, и на каждой итерации цикла ваш код будет замечать наличие соединения, получать для него сокет, а затем создавать поток для обработки сообщения.

Одна вещь, которую я заметил в вашем коде - когда вы порождаете поток для вызова interpretMessage, вы не предоставляете никаких аргументов функции, и поэтому каждый поток будет работать без какого-либо контекста о том, как он был создан. , Было ли это преднамеренным?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...