programing

C에서 소켓 연결부를 완전히 파괴하는 방법

lastcode 2023. 10. 24. 21:21
반응형

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;

그러나 'label'로 이동한 후 코드가 종료되고 오류 메시지가 표시되기 때문에 close(sock)가 연결 파괴를 완전히 닫지 않는 것으로 보입니다.

Unable to bind: Address already in use

그것은 연결이 다시 일어나지 않는다는 것입니다.무엇이 문제가 될 수 있습니까?미리 감사드립니다.

편집: 제가 실제로 원하는 것은 연결을 끊은 후 처음부터 스크립트를 실행할 때 새 프로그램으로 실행되어야 한다는 것입니다.어떻게 하면 되죠?

closecall은 TCP 소켓이 닫혔음을 표시할 뿐입니다.공정상 더 이상 사용할 수 없습니다.그러나 커널은 일정 기간 동안 일부 리소스(TIME_WAIT, 2MLS 등)를 보유할 수 있습니다.

SO_REUSEADDR을 설정하면 바인딩 문제가 제거됩니다.

그래서 그 가치를 확인하세요.true전화를 걸 때 0이 아닙니다.setsockopt(overflow 버그가 덮어쓸 수 있음):

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

있어pid변수는 코드입니다.사용하는 경우fork(접속 처리 프로세스를 시작하는 경우), 종료해야 합니다.sock그것이 필요하지 않은 공정에서도.

처음에는 이름을 붙이기 때문에, 우리는 모두 같은 것들의 이름을 같게 짓습니다.

서버측:

소켓이 다음으로 넘어갔습니다.listen()그다음에accept()청취소켓을 부르도록 하겠습니다.소켓이 반환되었습니다.accept()승인된 소켓을 호출합니다.

클라이언트 측:

소켓이 다음으로 넘어갔습니다.connect()연결/연결 소켓을 호출합니다.


문제와 관련하여:

종료하려면accept()ed connection은 선택적으로 먼저 사용한 후 다음을 사용하여 수락된 소켓(연결되었다고 부르는 것)을 닫습니다.

그런 다음 에 대한 호출 직전에 새 연결 루프를 수락하려면 다음과 같이 하십시오.accept(), 경유하지 않음bind()그리고.listen()다시.

오직. 종료 및 보류 중인 것을 제거하려면 청취 소켓을 닫습니다. connect()뒤에 발행된accept()반환된

연결된 소켓을 닫는 것을 잊었기 때문에 연결이 여전히 활성화되어 있습니다.청취 소켓을 닫는다고 해서 연결된 소켓이 자동으로 닫히지는 않습니다.

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

나는 당신이 왜 EADDRIN을 사용하는지 잘 모르겠습니다.그 코드는 리눅스와 macos 둘 다에서 잘 작동했습니다.

시스템 종료(2)를 사용해야 합니다.

은 입니다.SO_REUSEADDR.

만약 당신이 청취자이고, 연결을 수락한다면, 당신은 전화를 해야 합니다.shutdown()전에close()(적어도 리눅스에서는).그냥 전화하면.close(), 당신은 접속을 닫기 위해 클라이언트가 보내고 있는 FIN을 ACK하지 않을 것이고, 클라이언트는 a에 갇힐 수 있습니다.CLOSE_WAIT주.

왜냐하면 연결은 상대방이 인정할 때나 일정 시간이 지난 후에 실제로 닫히기 때문입니다.이건 정상적인 행동입니다...

편집: 코드를 실제로 확인하지는 않았지만 다른 사용자의 댓글을 보면 잘못된 행동을 하고 있습니다.

언급URL : https://stackoverflow.com/questions/10619952/how-to-completely-destroy-a-socket-connection-in-c

반응형