socket통신에서 read, write, Sigalrm에 대해 질문을 좀 드리겠습니다.

anaud2의 이미지

안녕하십니까
KLDP에서 항상 많은 도움을 받고 있어서 절 도와주시는 모든분들께 깊은 감사의 말씀드립니다.

오늘은 혼자서 고민을 해봤는데 도저히 답이 나오지 않는 패턴때문에 질문을 드리겠습니다.
리눅스에서 소켓통신을 하구요 블락단위로 통신을 하고 있구요 전송이나 수신중 데이터를 덜 받는상황이 발생할까봐
메세지가 정상적으로 송수신하게 특정 바이트만큼 무한루프를 돌고 있습니다.
(블락단위로 송수신을 하면 데이터 손실이 발생하지 않는다고 듣긴했는데 윗분의 지시때문에 꼭 넣어야 합니다.)
송수신 함수입니다.

int sendMSG(int sock, void *buf, int bufLen){
    int len=0;
    while((len = write(sock, buf, bufLen)) >= 0){
        bufLen -= len;
        buf += len;
        if(!bufLen){
            return 0;
        }
    }
    close(sock);
    return -1;
}
int recvMSG(int sock, void *buf, int bufLen){
    int len = 0;
    while((len = read(sock, buf, bufLen)) >= 0){
        bufLen -= len;
        buf += len;
        if(!bufLen){
            return 0;
        }
    }
    close(sock);
    return -1;
}

메인 함수의 시그날및 송수신 부분입니다.
static void sig_handler(int signo)
{
    return;
}
main()
  /* timeout 설정 */
    struct sigaction sigact, oldact;
    sigact.sa_handler = sig_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_flags |= SA_INTERRUPT;
    if(sigaction(SIGALRM, &sigact, &oldact) < 0)
    {
        perror("sigaction error : ");
        exit(0);
    }
    //중략
         alarm(Timeout);
        if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
        {
            if(errno == EINTR)
            {
                close(sock);
                return CODE3007;
            }
            return CODE3002;
        }
        alarm(0);
        printf("connect ok\n");
        alarm(Timeout);
        if((sendout = sendMSG(sock, &request, sizeof(request))) < 0){
 
            if(errno == EINTR)
            {
                close(sock);
                return CODE3007;
            }
            return CODE3003;
        }
        alarm(0);
        alarm(Timeout);
        if((sendout= recvMSG(sock, &reply, sizeof(reply))) < 0){
 
            if(errno == EINTR)
            {
                close(sock);
                return CODE3007;
            }
            return CODE3004;
        }
        alarm(0);     

제일 위에는 함수는 send와 recv를 전송하려고 한 구조체의 크기만큼 전송이 되었는지, 전송이 되지 않았다면 전송이 될때까지 무한루프를 돌리게 되어있습니다.
서버는 connet가 들어오면 받아주고 바로 종료를 해버립니다.클라이언트 소켓을 close하구요

위와같이 했었때 독특한 현상이 발생을 했는데요
일단 첫번째는 write함수의 경우 무조건 서버가 종료가 되어도 전송을 해버립니다.이부분은 서버의 버퍼에 넣어주기에 가능하지 않을까라는 생각이 들구요.

두번째는 recvMSG에서 무한루프를 돌고 있습니다. 이문제 또한 위의 함수에서 보면 recv() >= 0 으로 했기에 서버가 종료 했을때는 0를 리턴하게 되어있는데 제가 만든 함수에서 보면 if(!bufLen) 일때만 정상 종료를 하게 했으니.. 무한루프를 도는건 당연하다고 생각이 듭니다. else if(len ==0)일때 -1 리턴을 하면 될꺼 같습니다.
첫번째나 두번째는 read나 write를 잘못이해해서 생기는 문제인거 같은데요

제가 정말 이해가 안되는건 세번째질문으로 SIGALRM을 했기 때문에 timeout만큼의 시간이 자났을때는 무한루프라도 시그알람이 울려서 거기에 대한 처리를 해야된다고 생각이 드는데요 왜 알람이 울려서 무한루프를 빠져 나오지 않았을까요? 전 이부분이 너무 이해가 안됩니다.

첫번째 와 두번째 질문은 제가 생각하는게 맞는지랑 세번째 시그널 처리가 안된 이유를 알고 계신분은 도움을 요청드립니다.

날씨가 많이 추워졌습니다. 경기가 많이 어렵고 해서 많은 분들이 힘드실텐데요 나쁜일이 이제 그만끝나고 좋은일이 생기길 바랍니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.