LINUX.ORG.RU

проблема с UDP Socket


0

0

Привет!

Отправляю UDP дейтаграмму с порта 5060 и читаю ответ с помощью
recvfrom. Для приема ответа создается отдельный сокет, которому
говорится

  Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, ...);

чтобы не было ошибки "socket already in use". tcpdump показывает, что
приходит ответ на порт 5060, sip port (elzhov_local - моя машина):

  14:32:45.312129 IP c-24-218-216-50.domain.com.sip > elzhov_local.sip: SIP, length: 461

Тем не менее вызов recvfrom

    n = recvfrom( sock_fd, buf, 2, //buf_len,
                  0,
                  (struct sockaddr *)&src_sockaddr,
                  (socklen_t *)&src_sockaddr_len) );

НЕ возвращается. Далее, запускаю на локальной машине простой клиент,
который шлет что-то прямо на порт 5060 - и recvfrom сразу читает это и
возвращает 2.

В чем тут может быть дело? Большое спасибо!

сильно похоже на винигрет в твоей голове

приводи куски кода с ДЕТАЛЬНЫМ описание логики и комментариями

cvv ★★★★★
()
Ответ на: комментарий от cvv

Винегрет прежде всего в коде, который написан просто хуже некуда :( А теперь и в моей голове, наверно. Кончено, буду в коде ковыряться - но приводить его здесь просто страшно. Просто, думал, может кто сразу сможет сказать, как такое может быть - что tcpdump ответ показывает, а recvfrom его не читает.

2mumg: в смысле "шарь дескриптор"? :)

murla
() автор топика
Ответ на: комментарий от murla

>как такое может быть - что tcpdump ответ показывает, а recvfrom его не читает.

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

>2mumg: в смысле "шарь дескриптор"? :)

он предполагает что решал задачу сходную с той что решаеш ты

cvv ★★★★★
()
Ответ на: комментарий от murla

>но приводить его здесь просто страшно.

главное нормально отформатируй

cvv ★★★★★
()
Ответ на: комментарий от cvv

> есть предположение что ты ни на том порте или не тот хост слушаешЬ но по твоему описанию ничего вообще понять нельзя

1) tcpdump показывает, что приходит пакет-ответ на порт .sip (5060):
  14:32:45.312129 IP c-24-218-216-50.domain.com.sip > elzhov_local.sip: SIP, length: 461

2) код эхо-клиента, кторым можно посылать пакеты на порт 5060, я взял
из книжки Стивенса, отсюда: http://www.piter.com/bugs/5-318-00535-7/unpv12e.tar

/* ============================================================== */
#include    "unp.h"

int main(int argc, char **argv)
{
    int                 sockfd;
    struct sockaddr_in  servaddr;

    if (argc != 2)
        err_quit("usage: udpcli <IPaddress>");

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(5060);
    Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

    sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

    dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));

    exit(0);
}

void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
    int n;
    char sendline[MAXLINE], recvline[MAXLINE + 1];

    while (Fgets(sendline, MAXLINE, fp) != NULL) {

        Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

        if (Readable_timeo(sockfd, 5) == 0) {
            fprintf(stderr, "socket timeout\n");
        } else {
            n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
            recvline[n] = 0;    /* null terminate */
            Fputs(recvline, stdout);
        }
    }
}

/* ============================================================== */

пакет от этого эхо-клиента - принимается.

murla
() автор топика
Ответ на: комментарий от murla

На сколько я понимаю ты используешь разные триды для посылки и приема
пакетов. Так вот, чтобы не заморачиваться с реюзом сокетов и проблемой
уже открытого порта, достаточно расшарить серверный сокет всем клиентам
для посылки сообщений. А именно биндишь сокет на 5060 и отдаешь UAS,
этот же дескриптор даешь каждому UAC для посылки сообщения.

Сожешь сделать так:

typedef struct
{
unsigned int sid;
unsigned int reference;
} SIP_SOCKET_T;

void sip_socket_acquire ( SIP_SOCKET_T * in_Socket )
{
if ( in_Socket->reference == 0 )
{
socket = socket (...);
bind ( sid , ... );
in_Socket->reference ++;
}
}

void sip_socket_release ( SIP_SOCKET_T * in_Socket )
{
if ( in_Socket->reference > 0 )
{
in_Socket->reference --;
if ( in_Socket->reference == 0 )
{
close ( in_Socket->sid );
}
}
}
Я бы это бы засунул в класс с гуард мьютексом. Сокеты во всех система
multy-thread safe, соответственно надо только защитить дескриптор и reference counter

mumg
()
Ответ на: комментарий от mumg

отформатировано:
typedef struct
{
    unsigned int sid;
    unsigned int reference;
} SIP_SOCKET_T;

void sip_socket_acquire ( SIP_SOCKET_T * in_Socket )
{
   if ( in_Socket->reference == 0 )
   {
      socket = socket (...);
      bind ( sid , ... );
   }
   in_Socket->reference ++;
}

void sip_socket_release ( SIP_SOCKET_T * in_Socket )
{ 
    if ( in_Socket->reference > 0 )
    {
       in_Socket->reference --;
       if ( in_Socket->reference == 0 )
       {
           close ( in_Socket->sid );
       }
    }
} 

mumg
()

>Отправляю UDP дейтаграмму с порта 5060 и читаю ответ с помощью
recvfrom.

приведённый тобою код клиента отправляет датаграммы со СЛУЧАЙНОГО порта и слушает ответ на порте с которого ушла датаграмма

>Тем не менее вызов recvfrom
>
>    n = recvfrom( sock_fd, buf, 2, //buf_len,
>                  0,
>                  (struct sockaddr *)&src_sockaddr,
>                  (socklen_t *)&src_sockaddr_len) );
>
>НЕ возвращается.

это клиент или сервер????

если это клент то не принимает датаграмму по причине описанной выше. если сервер то код сервера в студию

а ещё советую познакомится с такой продвинутой тулзой как netstat

cvv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.