На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила трёх "С"
Пожалуйста,
1. Соблюдайте правила Форума.
2. Слушайте советы Модераторов.
(например, http://forum.sources.ru/index.php?act=ST&f=7&t=80382 )
3. Сверяйтесь с учебником по Великому и Могучему
  
> Сокеты в Solaris 2.5.1
    Картринка такая:
    Работает сервер. К нему есть клиент. Протокол ТСП.
    Клиент формирует сообщения и посылает их серверу. Сервер их обрабатывает и посылает клиенту ответ.
    Если серверный процесс заваливается, то клиент тоже падает
    на функции send() (не возвращает ошибочный код завершения, а просто падает процесс)
    Это происходит в том случае, если размер передаваемого сообщения превышает  
    определенный предел (около 600 байт). Если размер сообщения менее этого предела,  
    то функция send() отрабатывает без ошибки, а следующая за ней recv() возвращает
    ошибочный код завершения. Повторяю: если размер сообщения увеличить, и завалить
    серверный процесс, то клиент просто валится без дампа ядра и вообще без каких-либо сообщений. Есть у кого-нибудь соображения по этому поводу ?
      То же самое под Solaris 2.6 работает нормально:
      функция send() возвращает ошибочный код завершения и я его могу нормально
      обработать
      Что с 2.5.1 ? Это глюк операционки ?
        From : Serguei Revtov                      2:5021/19.1     06 May 02  09:06:32
        To   : Valery Votintsev                    2:5021/4.22     06 May 02  09:06:32
        Subj : Solaris question
        -------------------------------------------------------------------------------

        > rm -rf $* <
        VV> ошибочный код завеpшения, а пpосто падает пpоцесс) Это пpоисходит в
        VV> том слyчае, если pазмеp пеpедаваемого сообщения пpевышает опpеделенный
        VV> пpедел (около 600 байт). Если pазмеp сообщения менее этого пpедела,
        По-видимому это связано с pазбивкой пакета на части (не помещается в один...
        стpанно, эзеpнетовский около 1.5кб со всеми хедеpами, паpаметp MTU)


        > rm -rf $* <
        VV> --------- То же самое под Solaris 2.6 pаботает ноpмально: фyнкция
        VV> send() возвpащает ошибочный код завеpшения и я его могy
        VV> ноpмально обpаботать Что с 2.5.1 ? Это глюк опеpационки ?
        По-видимому связано с конкpетной веpсией. По идее должно бы быть пофиксено.
        Поискал на стаpом SunSolve CDROM, сходу нашлось следующее. Hемного похожее на
        описанную пpоблему. Пpавда фикса не видно. Если сильно интеpесно, можно
        спpосить у меня в эхе, может кто знает... Или на sunsolve.sun.com, там свежая
        инфоpмация.
        ExpandedWrap disabled
          <br>=== Begin 4291038 ===<br> Bug Id: 4291038<br> Category: kernel<br> Subcategory: tcp-ip<br> State: closed<br> Synopsis: TCP does not raise OOB exception on select call if the OOB has not<br>arrived.<br> Description:<br>TCP OOB data has two parts. The first part is the URGENT bit on the TCP flags.<br>The second part is the Urgent pointer. It is possible for the urgent pointer<br>to point to a data byte that is far downstream from the current sequence<br>number.<br>This happens particularly if the data stream is stopped by flow control. In<br>this case, the pointer will point to the end of the send buffer, and will<br>be sent in a packet with no data.<br><br>The correct reponse is for TCP to deliver the notification that urgent data has<br>been sent to the process via the exception mechanism of select, but the<br>attempt to read the data via recv should return EWOULDBLOCK. Instead, the<br>exception is not raised at all.<br><br>This has been seen in 2.5.1 and before.<br><br>A test case:<br>cat rec.cc<br>#include <sys/types.h><br>#include <sys/socket.h><br>#include <netinet/in.h><br>#include <netdb.h><br>#include <stdio.h><br>#include <stdlib.h><br>#include <sys/uio.h><br>#include <unistd.h><br>#include <strings.h><br><br>#define TRUE 1<br><br>/*<br> *  This program creates a socket and then begins an infinite loop. Each time<br> *  through the loop accepts a connection and print out messagess from it.<br> *  When the connection breaks, or a termination messages comes through, the<br> *  program accepts a new connection.<br> */<br><br>main ()<br>{<br>        int sock, length;<br>        struct sockaddr_in server;<br>        int msgsock;<br>        char buf[1024];<br>        int rval;<br>        int i;<br><br>        /* Create socket */<br>        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {<br>                perror("opening stream socket");<br>                exit(1);<br>        }<br><br>        /* Name socket using wild card */<br>        bzero(&server,sizeof(server));<br>        server.sin_family = AF_INET;<br>        server.sin_addr.s_addr = htonl(INADDR_ANY);<br>        server.sin_port = htons(9877);;<br>        if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {<br>                perror("binding stream socket");<br>                exit(1);<br>        }<br><br>        /* Find out assigned port number and print it out */<br>        length = sizeof server;<br>        if (getsockname(sock, (struct sockaddr *)&server, &length) < 0) {<br>                perror("getting socket name");<br>                exit(1);<br>        }<br><br>        printf ("Socket port #\%d\n", ntohs(server.sin_port));<br><br>        /*<br>        int sockBufSize = 120000;<br>        setsockopt (sock, SOL_SOCKET, SO_RCVBUF,<br>                    (char*)&sockBufSize, sizeof(sockBufSize));<br>        */<br><br>        setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,<br>                    (char*)&buf, sizeof(buf));<br><br>        listen(sock, 5);<br>        do  {<br>                msgsock = accept(sock, (struct sockaddr *)0, (int *)0);<br>                if (msgsock == -1)<br>                        perror("accept");<br>                else do {<br>                    while (1)<br>                    {<br>                        int status;<br>                        fd_set exception, readmask;<br>                        FD_ZERO (&exception);<br>                        FD_ZERO (&readmask);<br>                        FD_SET(msgsock, &exception);<br>                        FD_SET(msgsock, &readmask);<br>/*                        status = select(msgsock+1, &readmask, NULL,<br>&exception, NULL);*/<br>                        status = select(msgsock+1, NULL, NULL, &exception,<br>NULL);<br>                        if (!FD_ISSET(msgsock, &exception))<br>                        {<br>                            static int i = 0;<br>                            if (((++i) \% 1024))<br>                            {<br>                                continue;<br>                            }<br>                            if ((rval = read(msgsock, buf, 1024)) < 0)<br>                                perror("reading stream message");<br>                            printf ("------> Clear \%d\n", rval);<br>                            sleep(1);<br>                            continue;<br>                        }<br>                        else<br>                        {<br>                            printf ("Got exception\n");<br>                            rval = recv(msgsock, buf, 1024, MSG_OOB);<br>                            if (rval < 0) {<br>                                perror("Read OOB failed");<br>                                exit(1);<br>                            }<br>                            if (rval == 0) {<br>                                printf("Hmm, got no bytes\n");<br>                            } else {<br>                                buf[rval]=0;<br>                                printf("Received \%d byte, OOB=\%s\n",rval,buf);<br>                            }<br>                            sleep (1);<br>                        }<br>                     }<br>                        memset(buf, 0, sizeof(buf));<br>                        if ((rval = read(msgsock, buf, 1024)) < 0)<br>                                perror("reading stream message");<br>                        i = 0;<br>                        if (rval == 0)<br>                                printf("Ending connection\n");<br>                        else<br>                                printf("-->\%s\n", buf);<br>                } while (rval != 0);<br>                close(msgsock);<br>        } while (TRUE);<br><br>        exit(0);<br>}<br><br>send.cc: cat send.cc<br>#include <sys/types.h><br>#include <sys/socket.h><br>#include <netinet/in.h><br>#include <netdb.h><br>#include <stdio.h><br>#include <stdlib.h><br>#include <sys/uio.h><br>#include <unistd.h><br>#include <arpa/inet.h><br>#include <netdb.h><br>#include <string.h><br>#include <signal.h><br>#include <fcntl.h><br>#include <errno.h><br><br>#define DATA "This is a test"<br><br>/*<br> *  this program creates a socket and initiates a connection with the socket<br> *  given in the command line. One message is sent over the connection and<br> *  then the socket is closed, ending the connection. The form of the<br> *  command line is "send_internet hostname portnumber<br> */<br><br>main (int argc, char **argv)<br>{<br>    int sock;<br>    long i;<br>    struct sockaddr_in server;<br>    struct hostent *hp;<br>    char buf[100000];<br>    int done;<br><br>    /* Connect socket using name specified be command line */<br>    server.sin_family = AF_INET;<br>    hp = gethostbyname(argv[1]);<br>    if (!hp) {<br>      fprintf(stderr, "\%s: unknown host\n", argv[1]);<br>      exit(2);<br>    }<br>    memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);<br>    done = 0;<br>    int sockBufSize = 16384;<br>    /*  Create socket */<br>    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {<br>          perror("opening stream socket");<br>          exit(1);<br>    }<br>    server.sin_port = htons(9877);<br><br>    if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0) {<br>            perror("Failed to connect to port");<br>            exit(1);<br>    } else {<br>            printf("Connected\n");<br>    }<br><br>    fcntl (sock, F_SETFL,  fcntl(sock, F_GETFL, 0) | O_NONBLOCK);<br>    int sndsize = 0, length = 0;<br>    getsockopt (sock, SOL_SOCKET, SO_SNDBUF,<br>                    (char*)&sndsize, &length);<br>    printf ("Send size = \%d, length = \%d\n", sndsize, length);<br>    sleep(5);<br><br>    int j = 0;<br>    int sizetosend = atoi(argv[2]);<br>    int bytes = sizetosend ;<br>    while (bytes == sizetosend)<br>    {<br>       bytes = write(sock, buf, sizetosend);<br>       if (bytes == -1 )<br>           printf ("write error = \%s\n", strerror(errno));<br>       printf("write bytes = \%d\n", bytes);<br>       j += bytes;<br>       sleep(1);<br>    }<br><br>    printf ("Blocked after sending \%d bytes\n", j);<br>    char junk;<br>    int result;<br>    junk = 'A';<br>    printf("Sending urgent data\n");<br>    result = send(sock, &junk, 1, MSG_OOB);<br>    printf("Send urgent data result = \%d\n", result);<br>    sleep(10);<br>    exit(0);<br>}<br><br><br>Rec will listen to a port, and then send will connect to the port. Send will<br>then send data, a bit at a time, until the write fails because it would block.<br>Send then sends a byte of urgent data. A snoop shows the byte being delivered,<br>but the select never returns in the Rec program.<br><br> Work around:<br><br>        Integrated in releases:<br> Duplicate of:<br> Patch id:<br> See also:<br> Summary:<br>=== End 4291038 ===<br>


        -- Serguei
          sir()cb.tver.ru || 2:5021/11.10 || 2:5021/19.1

        --- GoldED+/W32 1.1.4.7
        * Origin: Welcome to ru.unix.solaris (2:5021/19.1)
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0285 ]   [ 15 queries used ]   [ Generated: 27.04.24, 12:57 GMT ]