Pro asynchronní připojení byste měli použít následující kroky:
- vytvořte soket pomocí
socket(..., SOCK_NONBLOCK, ...)
- zahájit připojení s
connect(fd, ...)
- pokud návratová hodnota není ani
0
aniEINPROGRESS
, poté přerušit s chybou - počkejte do
fd
je signalizováno jako připraveno k výstupu - zkontrolujte stav soketu pomocí
getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
- hotovo
Žádné smyčky – pokud nechcete zpracovat EINTR
.
Pokud je klient spuštěn jako první, měla by se zobrazit chyba ECONNREFUSED
v posledním kroku. Pokud k tomu dojde, zavřete zásuvku a začněte od začátku.
Je těžké říct, co je s vaším kódem špatně, aniž byste viděli další podrobnosti. Předpokládám, že při chybách ve vašem check_socket
nepřerušíte operace.
Existuje několik způsobů, jak otestovat, zda je neblokující připojení úspěšné.
- nejprve zavolejte getpeername(), pokud selže s chybou ENOTCONN, spojení se nezdařilo. pak zavolejte getockopt s SO_ERROR, abyste získali čekající chybu na soket
- volání čtení s délkou 0. pokud se čtení nezdařilo, spojení selhalo a errno for read indikuje, proč se spojení nezdařilo; read vrátí 0, pokud je připojení úspěšné
- zavolejte znovu a připojte se; pokud je errno EISCONN, připojení je již připojeno a první připojení bylo úspěšné.
Ref:UNIX Network Programming V1
D. J. Bernstein shromáždil různé metody, jak zkontrolovat, zda je asynchronní connect()
hovor byl úspěšný nebo ne. Mnoho z těchto metod má na určitých systémech nevýhody, takže psaní přenosného kódu pro ně je neočekávaně obtížné. Pokud si někdo chce přečíst všechny možné metody a jejich nevýhody, podívejte se na tento dokument.
Pro ty, kteří chtějí pouze verzi tl;dr, je nejpřenosnějším způsobem následující:
Jakmile systém signalizuje soket jako zapisovatelný, nejprve zavolejte getpeername()
zjistit, zda se připojil nebo ne. Pokud bylo volání úspěšné, zásuvka se připojila a můžete ji začít používat. Pokud toto volání selže s ENOTCONN
, připojení se nezdařilo. Chcete-li zjistit, proč to selhalo, zkuste přečíst jeden bajt ze soketu read(fd, &ch, 1)
, což také selže, ale chyba, kterou dostanete, je chyba, kterou byste dostali z connect()
kdyby to nebylo neblokující.