Autor Wątek: [ROZWIĄZANY] sendto() wywala proces po zakończeniu połączania UDP  (Przeczytany 2191 razy)

# Lipiec 05, 2013, 22:24:14
Edit: PROBLEM ROZWIAZANY
sendto wywalał reciveto

sendto() wywala proces po zakończeniu połączania UDP.
czyli jak zamykam klienta to wywala serwer

sendto() - docelowo powinno działać nawet z nieprawidłowym adresem i danymi

Trzeba w ustawieniach to zmienić lub przechwycić wyjątek/sygnał.

Próbowałem:
1.
signal(SIGPIPE, funkcja_obsługująca);ale pisze: SIGPIPE undefined...

2.
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));ale pisze: SO_NOSIGPIPE undefined

3.
sendto(int sockfd, const void *buf, size_t len,MSG_NOSIGNAL,const struct sockaddr *dest_addr, socklen_t addrlen);ale pisze: MSG_NOSIGNAL undefined

« Ostatnia zmiana: Lipiec 06, 2013, 16:18:45 wysłana przez Władek »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline magik6000

  • Użytkownik

# Lipiec 06, 2013, 01:14:17
#include <sys/socket.h>
#include <sys/types.h>   
?

EDIT:
Swoją drogą, próbowałeś użyć debuggera, aby dokładniej zlokalizować błąd("call stack" może być tutaj przydatny) - czy na pewno wywala się na sendto? Nie masz konstrukcji typu:
[qoute]sendto(fd,[..],tab[fd]->data,[..]);[/qoute]
?
« Ostatnia zmiana: Lipiec 06, 2013, 01:25:57 wysłana przez magik6000 »

Offline bies

  • Użytkownik

# Lipiec 06, 2013, 02:08:39
Swoją drogą, próbowałeś użyć debuggera, aby dokładniej zlokalizować błąd("call stack" może być tutaj przydatny) - czy na pewno wywala się na sendto? Nie masz konstrukcji typu:
To nie jest błąd, tak działa sendto(), jeśli klient się rozłączy i nie wyłączysz sygnałów dostajesz SIGPIPE.

# Lipiec 06, 2013, 12:54:13
#ifdef W32_SOCKETS
#else// linux
/* SIGPIPE is generated when a remote socket is closed */
void (*handler)(int);
handler = signal(SIGPIPE, SIG_IGN);
if ( handler != SIG_DFL ) {
signal(SIGPIPE, handler);
}
#endif
U innych jest to tak zrobione. Niestety na windowsie nie ma swojego odpowiednika

Offline Xion

  • Redaktor
    • xion.log

  • +1
# Lipiec 06, 2013, 14:11:41
Cytuj
Niestety na windowsie nie ma swojego odpowiednika
Na Windowsie sygnały nie mają odpowiednika, więc wtf you are talking about?...

# Lipiec 06, 2013, 15:19:07
Zauwarzyłem że sendto() nie wywala tylko jeśli jest wywoływany zaraz po reciveto()
albo w bardzo krótkim czasie

czyli nie mogę zapisać do struktury adresu i potem co jakiś czas wywoływać sendto(adres)
tylko muszę zaraz po otrzymaniu reciveto od razu wywoływać sendto() - w bardzo krótkim czasie.

Jeśli po 0.5 sekundzie wywołam sendto() na adres i port który nie przyjmuje pakietów to crash.

Może to jakieś ustawienia systemu windows?
« Ostatnia zmiana: Lipiec 06, 2013, 15:20:55 wysłana przez Władek »

Offline dynax

  • Użytkownik

# Lipiec 06, 2013, 16:19:32
Zauwarzyłem że sendto() nie wywala tylko jeśli jest wywoływany zaraz po reciveto()
albo w bardzo krótkim czasie

Ciekawa analiza behawioralna. Ja bym ci jednak osobiście nie radził o to opierać swojego kodu.

Offline bies

  • Użytkownik

# Lipiec 06, 2013, 17:56:59
Na Windowsie sygnały nie mają odpowiednika, więc wtf you are talking about?...
Częsty błąd. Częściowo mają (nie jest to pełny zestaw POSIX): http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx

Jednakowoż sendto() na Windows nie powoduje sygnału SIGPIPE (ten akurat nie występuje). Więc raczej błąd Władka jest inny.

Offline Xion

  • Redaktor
    • xion.log

# Lipiec 06, 2013, 18:26:41
Cytuj
Częsty błąd. Częściowo mają (nie jest to pełny zestaw POSIX):
Nie tylko nie jest to pełny zestaw, ale też zachowują się inaczej (np. obsługa "sygnału" SIGINT spawnuje osobny wątek). Więcej szczegółów np. tu: http://blogs.msdn.com/b/shrib/archive/2008/05/23/signals-on-windows.aspx

Jesli już chcemy znaleźć odpowiednik sygnałów w Windows, to komunikaty WM_ między aplikacjami z GUI będą chyba lepszą analogią.

Offline Rolek

  • Użytkownik

# Lipiec 06, 2013, 21:49:48
UDP jest protokołem bezpołączeniowym, więc trudno w tym przypadku mówić o zakończeniu połączenia ;)
Najwyżej, jeśli dostaniesz ICMP o nieosiągalności portu to WinSock może odmówić dalszego wysyłania danych przez dany socket.

Nie słyszałem o takiej funkcji jak reciveto(), nie chodziło Ci przypadkiem o recvfrom()?

Czy podajesz sendto() prawidłową strukturę z adresem? sockaddr_in musi być wypełniony na końcu ośmioma bajtami zer (żeby jego rozmiar był równy rozmiarowi sockaddr), natomiast sockaddr_in6 jest większy od sockaddr.
 


Na Windowsie, sygnały są obsługiwane przez msvcrt (lub inne msvcr*), w samym Windowsie nie ma ich obsługi i żadna funkcja WinAPI (w tym WinSock) nie wygeneruje sygnału.

np. obsługa "sygnału" SIGINT spawnuje osobny wątek
SIGINT w ogóle nie jest używany. Windows posiada własny mechanizm obsługi Ctrl+C dla aplikacji konsolowych i to on powoduje utworzenie nowego wątku.

Jesli już chcemy znaleźć odpowiednik sygnałów w Windows, to komunikaty WM_ między aplikacjami z GUI będą chyba lepszą analogią.
IMHO, lepszym odpowiednikiem sygnałów są raczej APC (ale właściwie tylko pochodzące z kernela;)
« Ostatnia zmiana: Lipiec 06, 2013, 21:54:35 wysłana przez Rolek »