일반적인 네트웍 프로그램에서 Client쪽 setsockopt()의 사용 방
고수분들께 질문 드립니다.
하나의 유니트에서 두 프로세서간 통신 방법으로 TCP Socket을 사용중입니다.
한쪽은 pSOS, 한쪽은 Linux인데 pSOS가 Server가 되고 Linux가 Clent가 되어 잘 사용하다가 필요에 의해 양쪽 모두에 setsockopt()로 socket option을 주었읍니다. 그런데 pSOS쪽은 제대로 option이 설정되는데 Client쪽인 Linux에서는 option이 error는 안나는데 효과가 나타나지 않습니다.
설정한 option은,
if(setsockopt(sock_id, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, optlen) < 0)
{
if(dbg_msg.socket_dbg)
printf("\r\n [ERROR] client : setsockopt() error : %s\n", strerror(errno));
close(sock_id);
usleep(100*1000);
continue;
}
if(setsockopt(sock_id, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, optlen) < 0)
{
if(dbg_msg.socket_dbg)
printf("\r\n [ERROR] client : setsockopt() error : %s\n", strerror(errno));
close(sock_id);
usleep(100*1000);
continue;
}
입니다. 물론 print문에서 보이다시피 Client쪽 코드입니다.
Client에서의 설정 위치는 socket() 후 connect() 사이입니다.
Server에서의 설정위치는 socket(), bind() 후 listen() 사이입니다.
질문의 요지는 pSOS인 Server에서 잘 듣는 socket option이 왜 Linux인 Client에서는 효과를 볼 수 없느냐는 겁니다. 위 코드에서 보듯이 error check를 하는데 분명히 error는 없었읍니다.
고수님들과 비슷한 문제로 고생하다 해결하신 분들의 답변 기다리겠읍니다.
즐거운 하루 되세요.
어떤 효과가 나타나지 않았다는 건지 정확한 상황을 제시해 주실수 있나요?
어떤 효과가 나타나지 않았다는 건지 정확한 상황을 제시해 주실수 있나요? 한번 저도 알고 싶네요..
일단, 클라이언트 단에서 KEEPALIVE와 NODELAY 옵션이 나타날 조건이 갖춰져 있는지요?
말 그대로 입니다.
말 그대로 KEEP_ALIVE와 NODELAY 기능이 효과가 없다는 뜻입니다.
Client가 죽으면 Server는 connection fail을 감지하는데 Client는 Server가 죽었다 살아나도 요지 부동으로 그냥 있읍니다.
그리고 send()시 예를 들어 2000 byte가 넘으면 2000 byte씩 잘라 보내는데 대부분 2000 byte씩 자르고 남은 나머지가 그대로 수신하는 Server에서 recv()에 나왔으면 하는데 그렇지 않더라는 얘기죠.
즉, 한 메시지와 다음 메시지를 보낼때 send() 후 return되는 length를 보면 분명히 한 메시지의 짜투리를 send()하고 다음 메시지를 새로 send() 하는데 수신하는 Server 입장에서 recv()를 print 해보면 메시지 경계가 합쳐져서 recv() 된다는 겁니다.
예를 들면,
첫번째 메시지 : size= 2050 bytes.
두번째 메시지 : size=150 bytes.
를 송신하고자 할때, 송신하는 Client에서는
send[2000] -----> 첫번째 메시지 시작
send[50] -----> 첫번째 메시지 나머지
send[150] -----> 두번째 메시지
이라고 print합니다.
그런데 수신하는 Server에서는
recv[2000] -----> 첫번째 메시시 시작
recv[200] -----> 첫번째 메시지 나머지 + 두번째 메시지
이라고 print합니다.
위와 반대로 동일한 메시지를 Server에서 송신하면 수신하는 Client에서는 송신한 그대로 수신합니다. 그래서 Server인 pSOS에서는 효과가 있고 Client인 Linux에서는 효과가 없다고 질문한 겁니다.
그리고, 물론 질문하신
"일단, 클라이언트 단에서 KEEPALIVE와 NODELAY 옵션이 나타날 조건이 갖춰져 있는지요?"에 대해서는 YES입니다.
페이지 맨 위 질문에서 언급했듯이 Client에서 socket()와 connect() 사이에 setsockopt()로 error check 해가면서 프로그램 했읍니다.
socket 통신은 지극히 정상적이며 단지 질문한 두가지 option이 효과가 없어서 글을 올린것입니다.
혹시 menu config에서 뭘 맞추어 주어야 하나요? 참고로 RedHat 8.0에 kernel은 2.4.18입니다.
아님, setsockopt()의 위치가 잘못 되었나요? 사실 위치는 중요하지 않다고 생각하고 제가 정한 위치가 맞다고 생각합니다.
좀 도와주세요.
Love means never having to say i'm sorry.
TCP_NODELAY이나 KEEPALIVE옵션은 그런 기능하고 관계가 없
TCP_NODELAY이나 KEEPALIVE옵션은 그런 기능하고 관계가 없습니다
보낼때 몇바이트씩 잘라보내더라도 읽는 쪽에서는 커널의 소켓 버퍼에 저장된 내용을 읽어오는 것이기 때문에 한꺼번에 읽어집니다. 따라서 기본적으로 TCP 소켓을 사용할 때는 보내는 쪽이건 받는 쪽이건 연결된 stream으로 간주해서 프로그래밍 해야 합니다. 서버와 client의 읽기 쓰기 위치에 따라 정상적으로 동작한것은 운이 좋았기 때문입니다.
그리고 상대쪽이 끊어졌을 때 detect()하는 방법은 read()를 해보거나 send()를 두번 해보는 것입니다. 정확한 상황은 모르겠지만 client가 죽으면 server에서 바로 인식하는 것은 server가 read()를 하고 있기 때문이고, server가 죽어도 client쪽에서 인식못한다는 것은 read()를 하지 않기 때문인 거 같습니다..
댓글 달기