2012-05-16 3 views
17

Я сделал клиент чата в linux, используя сокет, и я хочу полностью уничтожить соединение. Ниже соответствующие части коды:Как полностью уничтожить соединение сокета в C

int sock, connected, bytes_recieved , true = 1, pid; 
char send_data [1024] , recv_data[1024];  
struct sockaddr_in server_addr,client_addr;  
int sin_size; 
label: 
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(3128);  
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 3128"); 
fflush(stdout); 
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size); 
//necessary code 
close(sock); 
goto label; 

но близко (носок) оленья кожа, кажется, чтобы закрыть полностью уничтожить соединение, потому что после того, как будет «метка» код выхода отображается сообщение об ошибке

Unable to bind: Address already in use 

Это соединение не происходит снова. В чем проблема? Заранее спасибо.

EDIT: Я действительно хочу, когда я запускаю сценарий с самого начала после уничтожения соединения, он должен работать как новая программа. Как мне это сделать?

+0

Почему вы это делаете? Вы должны вернуться обратно до 'accept', а не заново создавать серверный сокет. – Mat

+0

Зачем вы хотите закрыть и снова открыть прослушивающий сокет вместо цикла «accept()»? – dwalter

+0

Возможный дубликат [Что такое SO_REUSEADDR (опция setsockopt) - Linux?] (Http://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option- linux) –

ответ

24

Звонок close только отмечает, что разъем TCP закрыт. Это невозможно использовать в процессе. Но ядро ​​может по-прежнему удерживать некоторые ресурсы за период (TIME_WAIT, 2MLS и т. Д.).

Настройка SO_REUSEADDR должна устранять проблемы с привязкой.

Поэтому убедитесь, что значение true действительно ненулевых при вызове setsockopt (переполнение ошибки может перезаписать):

true = 1; 
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) 

Существует pid переменного код. Если вы используете fork (для запуска процессов обработки соединений), вы должны закрыть sock также в процессе, который ему не нужен.

-1

Хорошо, потому что соединение действительно закрыто, когда другая сторона подтверждает его или после определенного таймаута. Это нормальное поведение ...

EDIT: Я на самом деле не проверить свой код, но с комментариями других пользователей, вы делаете что-то неправильно ...

0

Вы должны использовать shutdown(2) системный вызов.

+1

Я пробовал, но все равно не повезло. Соединение не разрушается. –

1

Сначала для nameing, так что мы все названия одинаковые вещи: одни и те же побочные

Сервер:

сокет передается listen(), а затем accept() давайте называть сокет. Сокет, возвращаемый accept(), позвоним принятому разъему.

стороне клиента:

сокет передается connect() назовём соединительный/подключенный разъем.


Что касается вашего вопроса:

Чтобы прекратить accept() ред подключение к закрыть принятый сокет (то, что вы называете подключен), сначала с помощью shutdown() с последующим close(). Чтобы принять новый контур соединения до того, как позвонить по телефону accept(), не, перейдите по адресу bind() и listen().

только выключение и закрыть сокет, если вы хотите, чтобы избавиться от ожиданияconnect() эмитированных после accept() вернулся.

1

Соединение по-прежнему активно, потому что вы забыли закрыть подключенный разъем. Закрытие гнезда для прослушивания автоматически не закрывает подключенный разъем.

//necessary code 
close(connected); // <---- add this line 
close(sock); 
goto label; 

Я не уверен, хотя почему вы получаете EADDRINUSE. Код работал нормально как на Linux, так и на Mac OS.

Смежные вопросы