#c #сокет
есть такой код: int read_s, str_size; char recive_msg[TEXTSIZE_BUFER]; struct sockaddr_in server, client; str_size = sizeof(struct sockaddr_in); server.sin_port = htons(100); server.sin_addr.s_addr = INADDR_ANY; server.sin_family = AF_INET; for (;;) { int socket_r = socket(AF_INET, SOCK_STREAM, 0), clnt_r; setsockopt(socket_r, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); setsockopt(socket_r, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); printf("22\n"); memset(server.sin_zero, '\0', sizeof(server.sin_zero)); if (bind(socket_r, (struct sockaddr *)&server, sizeof(server)) < 0) goto close_socket; printf("aa\n"); listen(socket_r, 10); if ((clnt_r = accept(socket_r, (struct sockaddr *)&client, &str_size)) <= 0) goto close_socket; read_s = recv(clnt_r, recive_msg, TEXTSIZE_BUFER, 0); printf("close\n>%s\n", recive_msg); close_socket: setsockopt(socket_r, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); setsockopt(clnt_r, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); close(clnt_r); close(socket_r); } Проблема: Когда софт выполняет SO_REUSEADDR и close(), возвращается в начале и потом секунд 20-30 циклится на printf("22\n");, только после этого идет дальше. Вопрос такой: в чем может быть причина? Изначально у меня задумка была поделить клиент и сервер часть в 2 отдельных потока...и когда освобождается порт выполняется тот или иной поток.
Ответы
Ответ 1
SO_REUSEADDR говорит, что этот сокет можно привязать к адресу, даже если он уже привязан. Делать его перед закрытием сокета - бессмысленно. Изменять эту опцию имеет смысл только, если сокет создан, но ещё не привязан.Ответ 2
В месте закрытия сокета поменять на следующий код: close_socket: shutdown(clnt_r, SHUT_RDWR); close(clnt_r); shutdown(socket_r, SHUT_RDWR); close(socket_r); } по вкусу, если таймаут закрытия велик на ваш взгляд, можно добавить: close_socket: struct linger lng = { 0, 0 }; if (setsockopt(clnt_r, SOL_SOCKET, SO_LINGER,(void*)(&lng), sizeof(struct linger)) < 0) { perror("set: linger 1"); } shutdown(clnt_r, SHUT_RDWR); close(clnt_r); if (setsockopt(socket_r, SOL_SOCKET, SO_LINGER,(void*)(&lng), sizeof(struct linger)) < 0) { perror("set: linger 2"); } shutdown(socket_r, SHUT_RDWR); close(socket_r); } но лучше искать причину медленного закрытия.. Она легко может быть и на стороне клиента. И в общем, с лингером не все так просто, вы изменяете запланированное поведение системы, в области очереди отправки пакетов. Это не всегда есть правильное решение. Если опция SO_LINGER разрешена, то вызовы close(2) или shutdown(2) приведут к задержке процесса до отправки всех сообщений в очереди сокета или до истечения времени задержки. В противном случае выход из вызовов будет произведен немедленно и закрытие будет произведено в фоновом режиме. Если сокет закрывается как часть вызова exit(2), то задержка всегда происходит в фоновом режиме. Собственно мануал В вашем случае, разумно пересмотреть код, делать bind и listen в цикле непонятно зачем.. система явно против.. :) В цикле надо читать из сокета, и возможно отвечать, уверен что клиент ожидает общения :) Функция accept и read должна быть в цикле, и её удобно обернуть во что то более приемлемое, для выхода из неё в случае ошибки. Попробуйте перейти к более приспособленным оберткам, избегая использование goto, например: do { accept() .... if (error) break; read() ... // другой код if (noerror) break; } while (0); close_socket_code()...
Комментариев нет:
Отправить комментарий