Привет!
Отправляю 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.
В чем тут может быть дело? Большое спасибо!
Винегрет прежде всего в коде, который написан просто хуже некуда :( А теперь и в моей голове, наверно. Кончено, буду в коде ковыряться - но приводить его здесь просто страшно. Просто, думал, может кто сразу сможет сказать, как такое может быть - что tcpdump ответ показывает, а recvfrom его не читает.
> есть предположение что ты ни на том порте или не тот хост слушаешЬ но по твоему описанию ничего вообще понять нельзя
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);
}
}
}
/* ============================================================== */
пакет от этого эхо-клиента - принимается.
На сколько я понимаю ты используешь разные триды для посылки и приема
пакетов. Так вот, чтобы не заморачиваться с реюзом сокетов и проблемой
уже открытого порта, достаточно расшарить серверный сокет всем клиентам
для посылки сообщений. А именно биндишь сокет на 5060 и отдаешь UAS,
этот же дескриптор даешь каждому UAC для посылки сообщения.
Сожешь сделать так:
typedef struct
{
unsigned int sid;
unsigned int reference;
} SIP_SOCKET_T;
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
>Отправляю UDP дейтаграмму с порта 5060 и читаю ответ с помощью
recvfrom.
приведённый тобою код клиента отправляет датаграммы со СЛУЧАЙНОГО порта и слушает ответ на порте с которого ушла датаграмма
>Тем не менее вызов recvfrom
>
> n = recvfrom( sock_fd, buf, 2, //buf_len,
> 0,
> (struct sockaddr *)&src_sockaddr,
> (socklen_t *)&src_sockaddr_len) );
>
>НЕ возвращается.
это клиент или сервер????
если это клент то не принимает датаграмму по причине описанной выше. если сервер то код сервера в студию
а ещё советую познакомится с такой продвинутой тулзой как netstat