Elohim Posted March 9, 2014 Report Posted March 9, 2014 Am si eu nevoie de un exemplu de o initializare a unui socket non-blocking ( pentru recv() sau global ) impreuna cu un timeout. Nu am incercat nimic inca, sunt ceva exemple pe stackoverflow, unul mai in ceata decat celalalt.De preferat C, daca nu, C++Multumesc in avans. Quote
Active Members MrGrj Posted March 9, 2014 Active Members Report Posted March 9, 2014 Uite, sper sa iti fie de ajutor.socket_inet_server.c#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>/*Author: MrGrjProgramming Language: CEnjoy */struct sockaddr_in sockserv;struct sockaddr_in from;int fromlen = sizeof (from),portno,pid=1;char msg[30],* fromip,buf[30];int ss,newsock[5],i=1;pthread_t tid[5];//.................thread-uri multiple...........void conexiune(void *socket_desc){ int newsock = *(int*)socket_desc; read(newsock,msg,30); fromip=inet_ntoa(from.sin_addr); printf("received folowing message - \" %s \" from ip=%s port=%d\n",msg,fromip,ntohs(from.sin_port)); sprintf(buf,"\nOK! Got it! %d\n",pthread_self()); write(newsock,buf,sizeof(buf));}//.................thread-uri multiple...........int main(){ if ((ss = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("server: socket"); _exit(1); } sockserv.sin_family=AF_INET; portno=60080; sockserv.sin_port=htons(portno); inet_aton("127.0.0.1", &sockserv.sin_addr); if (bind(ss, (struct sockaddr *)&sockserv, sizeof(sockserv)) < 0) { perror("server: bind"); _exit(1); } listen(ss,2);/*--------------------------varianta cu procese multiplewhile(i<3){ newsock = accept(ss, (struct sockaddr *)&from, &fromlen); printf("\n%d connected\n",i); i++; printf("\nbefore fork.... pid=%d ppid=%d\n",getpid(),getppid()); if(pid!=0) pid=fork(); printf("\nafter fork.... pid=%d ppid=%d\n",getpid(),getppid()); if(pid==0) { read(newsock,msg,30); fromip=inet_ntoa(from.sin_addr); printf("received folowing message - \" %s \" from ip=%s port=%d\n",msg,fromip,ntohs(from.sin_port)); sprintf(buf,"\nOK pid=%d ppid=%d\n",getpid(),getppid()); write(newsock,buf,sizeof(buf)); sleep(10); } else { printf("\nclosing pid=%d ppid=%d\n",getpid(),getppid()); close(newsock); }}//------------------varianta cu procese multiple *///.................thread-uri multiple...........while(i<3){ newsock = accept(ss, (struct sockaddr *)&from, &fromlen); printf("\n%d connected\n",i); pthread_create(&tid,NULL,conexiune,(void*)&newsock); i++;}pthread_join(tid[1],NULL);pthread_join(tid[2],NULL);//.................thread-uri multiple...........sleep(10);close(newsock);close(ss);_exit(0);} Quote
aelius Posted March 9, 2014 Report Posted March 9, 2014 (edited) Salut,Asta te coafeaza ?https://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzab6%2Frzab6xnonblock.htm @MrGrj esti sigur ca este non-blocking exemplul ? Edited March 9, 2014 by aelius Quote
Elohim Posted March 9, 2014 Author Report Posted March 9, 2014 @aelius, fix acel articol l-am recitit de peste 30 de ori pana sa postez acest thread. Motivul era ca preferam sa nu folosesc select() . Cred ca inca un lucru care l-am omis sa specific, este ca ma intereseaza acest lucru dpdv al client-ului, nu al server-ului.Exemplu foarte scurt:EU.connect -> serverServer -> "hey"Eu -> "sup mofo?"Server ->In cazul in care Server refuza sa imi mai dea vreun mesaj inapoi, dar nici nu imi inchide sesiunea, risc sa stau cu socket-ul pornit pana inchid programul, lucru care incerc sa il evit. Multe exemple implica select(), nu am nici cel mai mic motiv sa evit aceasta functie, dar abia am inceput cu C, si select mi se pare un pic peste mine.Se pare ca trebuie sa mai citesc.Multumesc pentru ajutor.Daca mai doreste cineva sa isi exprime parerea cu un exemplu, nu neaparat de pe Google, este binevenit. Quote
Active Members MrGrj Posted March 9, 2014 Active Members Report Posted March 9, 2014 Salut,Asta te coafeaza ?https://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzab6%2Frzab6xnonblock.htm @MrGrj esti sigur ca este non-blocking exemplul ?Imi cer scuze, era tarziu si am citit prost. Quote
Nytro Posted March 9, 2014 Report Posted March 9, 2014 Salut,Invata si foloseste select + FD_CLR, FD_ISSET, FD_SET, FD_ZERO.Ce face: iti permite sa verifici daca pe unul sau mai multi socketi ai date de intrare, date de iesire sau erori. Adica daca ai primit date (in cozile din kernel) pe acel socket, daca urmeaza sa fie trimise date pe acel socket sau daca a intervenit o eroare pe acel socket, de exemplu inchiderea conexiunii.Ce e important la acest "select" e ca poti "astepta" pe un socket un anumit interval (sau poti sa nu astepti) sa se intample un astfel de eveniment (primire date de exemplu). Adica poti verifica daca pe socket ai date de intrare. Daca ai, le procesezi, daca nu ai, treci mai departe. Sau poti astepta 3000 ms sa primesti date. Dupa 3000 ms, daca ai primit date, le procesezi, daca nu, faci altceva.Nu e foarte complicat si sunt tutoriale care explica in detaliu acest syscall.PS: Daca vrei Windows, pe langa select, ai o serie completa de functii asincrone (cele cu Async) care au ca parametru o functie callback care e apelata exact cand e declansat un eveniment (ca primirea de date). 1 Quote
compile Posted March 9, 2014 Report Posted March 9, 2014 select este foarte util (mai ales pe partea de server) dupa ce ai invatat sa-l folosesti dar daca am inteles bine tu cauti un recv care sa faca timeout si in cazul asta select e overkill.recv va returna -1 cu eroarea WSAEWOULDBLOCK atunci cand incerci sa citesti dintr-un socket non-blocking unde nu este nimic de citit asa ca e simplu sa pui recv intr-un loop verificand diferenta de timp.Ti-am facut un exemplu rapid pentru win:#include <winsock2.h>#include <stdio.h>#pragma comment(lib, "ws2_32.lib")bool make_nonblocking(SOCKET sock){ u_long mode = 1; return ioctlsocket(sock, FIONBIO, &mode) != SOCKET_ERROR;}int recv_to(SOCKET sock, char* buff, int len, int flags, unsigned int tout){ DWORD start = GetTickCount(); int ret = recv(sock, buff, len, flags); while(ret == -1 && WSAGetLastError() == WSAEWOULDBLOCK) { Sleep(10); if(GetTickCount() - start > tout) { SetLastError(WSAETIMEDOUT); return -1; } ret = recv(sock, buff, len, flags); } return ret;}int main(){ WSADATA wsd; if(WSAStartup(0x0202, &wsd) == 0) { SOCKET sock =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sock != INVALID_SOCKET) { sockaddr_in sa; memset(&sa, 0, sizeof(sockaddr_in)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(99); if(connect(sock, (sockaddr*)&sa, sizeof(sockaddr_in)) != SOCKET_ERROR) { if(make_nonblocking(sock)) { char buff[33]; memset(buff, 0, sizeof(buff)); int ret = recv_to(sock, buff, 32, 0, 5000); printf("ret=%i\n", ret); printf("err=%i\n", WSAGetLastError()); } closesocket(sock); } } WSACleanup(); } getchar(); return 0;} Quote
Comunistul Posted March 9, 2014 Report Posted March 9, 2014 (edited) Absolut orice model inafara de cel dat original ca default cand folosesti ori Winsock ori UNIX sockets este blocking.Cele de mai jos sunt non-blocking. Exemple gasesti pe tot netul - dar fi atent - bad practice vor fi in toate. Citeste manualul official pentru a nu face aceleasi greseli ca si altii...ioctlsocket() e functia care schimba socket mode-ul manual.Windows:select & pollingWSAAsyncSelectWSAAsyncEventOverlapped EventsOverlapped RoutinesI/O Completion PortsLinux:SelectEpollAIOSelect merge mult mai bine pe Linux in comparatie cu alte systeme, dar Epoll e recomandat.Pe Windows - daca nu vrei sa te faci de tot rahatul - IOCP sau Overlapped. Edited March 9, 2014 by Comunistul Quote
Elohim Posted March 9, 2014 Author Report Posted March 9, 2014 @compile, da, intr-adevar doar de un recv() cu timeout aveam nevoie, exemplul tau ar parea ca se potriveste perfect. O sa ii fac o proba acum.Multumesc celor care au postat.Daca nu trec prea multe zile, o sa postez solutia scrisa de mine, pentru future refferences. Quote