Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced Sockets in UNIX / Linux References: Internetworking with TCP/IP (Comer) (Linux / POSIX Sockets Version) UNIX Network Programming Vol. 1, 2ed.(Stevens)

Similar presentations

Presentation on theme: "Advanced Sockets in UNIX / Linux References: Internetworking with TCP/IP (Comer) (Linux / POSIX Sockets Version) UNIX Network Programming Vol. 1, 2ed.(Stevens)"— Presentation transcript:

1 Advanced Sockets in UNIX / Linux References: Internetworking with TCP/IP (Comer) (Linux / POSIX Sockets Version) UNIX Network Programming Vol. 1, 2ed.(Stevens) Linux Sockets Programming (Walton)

2 cs423-cotter2 Addressing Support getsockname (socket, name, namelen) –return value = 0 on success, SOCKET_ERROR on failure –socket = SOCKET –name = struct sockaddr * –namelen = socklen_t * sizeof(sockaddr)

3 cs423-cotter3 Addressing Support getpeername(socket, remaddr, addrlen) –return value = 0 on success, SOCKET_ERROR on failure –socket = SOCKET –remaddr = struct sockaddr * –addrlen = socklen_t *sizeof(sockaddr)

4 Getaddrinfo Combines: –gethostbyname () – (getipnodebyname() ) –gethostbyaddr() – (getipnodebyaddr() –getservbyname() –getservbytport() Designed to support IP v4, IP v6 Can return a linked list of addr structures that can be used by bind (), connect (), etc. –Sorts list by relevance. 4cs423-cotter

5 Getaddrinfo int getaddrinfo ( char *host, char *service, struct addrinfo *hints, struct addrinfo **res); –struct addrinfo { int ai_flags; int ai_family; int socktype; int ai_protocol; size_tai_addrlen; struct sockaddr * ai_addr; char * ai_cannonname; struct addrinfo * ai_next; } 5cs423-cotter

6 Send / recv Options FlagDescriptionRECVSEND MSG_DONTROUTE MSG_DONTWAIT MSG_PEEK MSG_WAITALL MSG_OOB Bypass routing table lookup Only this operation is nonblocking Peek at incoming message Wait for all the data Send or receive out-of-band data ******** ****** recv (s, buf, sizeof(buf), flags);

7 Out-of-band / Urgent Data Objective is to pass urgent data as part of a TCP packet that may also include regular (inband) data. TCP urgent pointer references a single byte in TCP data. That single byte is what gets returned as urgent (OOB) data. Sending OOB data: send (s, buf, strlen(buf), MSG_OOB); sendto (s, buf, strlen(buf), MSG_OOB, (struct sockaddr FAR *)&sin,sizeof(sin));

8 Receiving OOB data - SIGURG signal (SIGURG, myUrgHandlr)//Identify signal Handler static void myUrgHandlr(int signo) { //signal handler int n; char buf[BUFSIZE]; n = recv(ss,buf,sizeof buf,MSG_OOB); buf[n] = '\0'; // null terminator for buffer printf("Urgent Data: '%s' (%d)\n", buf,n); // reset the signal handler. signal(SIGURG,sigurg); }

9 Receiving OOB data - 2 int main(int argc, char *argv[]) { char*service = "6543";/* service name or port number*/ struct sockaddr_in fsin;/* the address of a client*/ unsigned intalen;/* length of client's address*/ int z; char buf[BUFSIZE]; switch (argc) { case1: break; case2: service = argv[1]; break; default: errexit("usage: TCPechod [port]\n"); } s = passiveTCP(service, QLEN);

10 Receiving OOB data - 3 /* * Catch SIGURG: * */ signal(SIGURG,sigurg); ss = accept(s, (struct sockaddr *)&fsin, &alen); /*Establish ownership so that we can catch SIGURG: */ z = fcntl(ss,F_SETOWN,getpid()); if ( z == -1 ) errexit("fcntl fail: %s\n", strerror(errno)); else printf("We own the socket\n");

11 Receiving OOB data - 4 while (1) { z = recv(ss,buf,sizeof buf,0); if ( z == -1 ) errexit("recv fail: %s\n", strerror(errno)); if ( z == 0 ) break; buf[z] = 0; printf("rcv '%s' (%d)\n", buf, z); } close(s); return 0; }

12 cs423-cotter12 Smart Select Some programs may require more than 1 thread (or process), but may be able to support more than 1 client per thread. Select can be combined with multi-tasking to provide appropriate levels of client support.

13 cs423-cotter13 Smart-select-server.c int main(int argc, char *argv[]) { : if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { listen(sd, 15); for (;;) { if ( NumChildren < MAXPROCESSES ) {int pid; if ( (pid = fork()) == 0 ) servlet(sd); else if ( pid > 0 ) NumChildren++; else perror("fork()"); } else sleep(1); } else perror("bind()"); return 0; }

14 14 Smart-select-server.c void servlet(int server) { fd_set set, rset; int maxfd = server; int ceiling=0; FD_ZERO(&set); FD_ZERO(&rset); FD_SET(server, &set); for (;;) { memcpy (&rset, &set, sizeof (fd_set)); struct timeval timeout={2,0}; // 2 seconds if ( select(maxfd+1, &rset, 0, 0, &timeout) > 0 ) { //---If new connection, connect and add to list--- if ( FD_ISSET(server, &rset) ) { if ( ceiling < MAXCONNECTIONS ) { int client = accept(server, 0, 0); if ( maxfd < client ) maxfd = client; FD_SET(client, &set); ceiling++; printf("select process #%d: %d connected\n", getpid(), ceiling); }

15 15 Smart-select-server.c else { int i; for ( i = 0; i < maxfd+1; i++ ) { if ( FD_ISSET(i, &rset) ) { char buffer[1024]; int bytes; bytes = recv(i, buffer, sizeof(buffer), 0); if ( bytes < 0 )// check if channel closed { close(i); FD_CLR(i, &set); ceiling--; printf("select process #%d: %d connected\n", getpid(), ceiling); } else//process the request send(i, buffer, bytes, 0); } }// end of for }//end of else }//end of if }//end of for exit(0); }

16 cs423-cotter16 Poll Function int poll (struct pollfd *fdarray, unsigned long nfds, int timeout) –Return: count of ready fds, -1 on error, 0 on timeout timeout: -1 wait forever, 0 no block, >0 wait for specified milliseconds. struct pollfd { intfd;//descriptor to check shortevents;//events of interest on fd shortrevents;//events that occurred on fd }

17 cs423-cotter17 Poll Events ConstantIn to events From revents Description POLLIN**Normal or priority data can be read POLLRDNORM**Normal data can be read POLLRDBAND**Priority band data can be read POLLPRI**High Priority data can be read POLLOUT**Normal data can be written POLLWRNORM**Normal data can be written POLLWRBAND**Priority data can be written POLLERR*An error has occurred POLLHUP*Hangup has occurred POLLNVAL*Descriptor is not an open file

18 cs423-cotter18 TCPpollechod.c #include,,,,,,, #defineQLEN 5// maximum connection queue length #defineBUFSIZE4096 #define MAX_OPEN 16 #define INFTIM -1 int main(int argc, char *argv[]) { char*service = "9877";// service name or port number struct sockaddr_in fsin;// the from address of a client intmsock, connfd, sockfd;// master server socket struct pollfd client[MAX_OPEN]; unsigned intalen;// from-address length intfd, nfds, maxi, nready, i, n; socklen_t clilen; charline[BUFSIZE];

19 cs423-cotter19 TCPpollechod.c switch (argc) { case1: break; case2: service = argv[1]; break; default: errexit("usage: TCPmechod [port]\n"); } msock = passiveTCP(service, QLEN); //Now we need to set up the polling process. client[0].fd = msock; client[0].events = POLLRDNORM; for (i=1; i < MAX_OPEN; i++) client[i].fd = -1;// -1 indicates available entry maxi = 0;

21 cs423-cotter21 TCPpollechod.c for (i = 1; i <= maxi; i++) // check all clients for data { if ( (sockfd = client[i].fd) < 0) continue; if (client[i].revents & (POLLRDNORM | POLLERR)) { if ( (n = read(sockfd, line, BUFSIZE)) < 0) { if (errno == ENOTCONN) { //connection reset close(sockfd); client[i].fd = -1; } else errexit("readline error"); } else if (n == 0) {// connection closed by client close(sockfd); client[i].fd = -1; } else { printf ("Got %d char from client %d\n", n, i); write(sockfd, line, n); } if (--nready <= 0) break;// no more readable descriptors } }} }

22 cs423-cotter22 IO control command ioctlsocket(socket, cmd, argp) –return value = 0 on success, SOCKET_ERROR on failure –cmd = socket command requested (long) FIONBIO (Set socket to non-blocking mode) FIONREAD (Determine the amount of pending data to be read) SIOCATMARK (Determine whether all OOB data has been read) –argp = pointer to return value (u_long *)

23 cs423-cotter23 Windows Non-Blocking if (ioctlsocket(sock, FIONBIO, &bflag)== SOCKET_ERROR) errexit("Can't set socket to be nonblocking %d\n",GetLastError()); : timer = clock(); // set the timer rcfm_ok = false; while ( clock() - timer < TIMEOUT) { cc = recvfrom(sock, buf, BUFSIZE, 0, (sockaddr *)&clt_addr, &alen); if ( cc>=0) //Should also test for error return!! { rcfm_ok = true; break; }

24 cs423-cotter24 Windows Non-Blocking The clock() function (part of time.h) counts in terms of milliseconds. (Independent of the hardware timer. The hardware timer might not be as precise. I think the Windows timer is on the range of 15 ms. ) In this example, we set the TIMEOUT value to 500 miliseconds (well within our level of precision). This allows us to wait for a predetermined amount of time (in this case 500 ms) until we give up on getting an answer.

25 cs423-cotter25 Linux Non-Blocking save_file_flags = fcntl(sock, F_GETFL); save_file_flags |= O_NONBLOCK; fcntl(sock, F_SETFL, save_file_flags); : while ( delay < TIMEOUT) { cc = recvfrom(sock, buf, BUFSIZE, 0, (sockaddr *)&clt_addr, (socklen_t*) &alen); if (cc < 0) { if (errno == EAGAIN) // we "nonblocked" out of the function { gettimeofday(&mytime, &myzone); endsec = mytime.tv_sec; endus = mytime.tv_usec; delay = endus - startus; } else //we had a real problem with recvfrom errexit ("recvfrom failed"); } else //We got some data. Go process it. { rcfm_ok = true; break; } } // end of delay while

26 cs423-cotter26 Linux Non-Blocking In this example, we first set the socket to be non-blocking. The form of that function is conceptually the same as for Windows, but it uses a different command. This program uses the gettimeofday command to check for the time. It returns a value that is precise to microseconds, although its accuracy is limited by the system timer for the OS / hardware. (typically 15 ms). If the socket is non-blocking, we will get an error return from recvfrom (-1). To tell the difference between a real error and a non- blocking return, we need to check the value of the global variable “ errno”. If it is equal to EAGAIN, then we left recvfrom because it was non-blocking. We test the time here to see how long we have been doing this loop. If we actually got some data, we would have cc > 0. That sends us to the last “else” loop which breaks us out of the loop. Otherwise we go back to the recvfrom and repeat until we run out of time.

27 cs423-cotter27 Socket Option commands getsockopt, setsockopt (socket, level, optname, optval, optlen) –return value = 0 on success, SOCKET_ERROR on failure –level = (Where option is interpreted) SOL_SOCKETIPPROTO_IPV6 IPPROTO_TCPIPPROTO_ICMPV6 IPPROTO_IP –opt = option selected SO_BROADCASTSO_RCVBUF SO_KEEPALIVESO_RCVTIMEO SO_OOBINLINE… –optval = address for value returned (void *) –optlen = length of option field (int *)

28 cs423-cotter28 Bcast_1.c Basic client preamble……… setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); signal(SIGALRM, recvfrom_alarm); while (fgets(sendline, MAXLINE, stdin) != NULL) { servlen = sizeof(sin); sendto(s,sendline,strlen(sendline),0,&sin,servlen); alarm(5); for ( ; ; ) { len = servlen; n = recvfrom(s,recvline,MAXLINE,0,&reply_addr,&len); if (n < 0) { if (errno == EINTR) break;// waited long enough for replies else errexit("recvfrom error"); }

29 cs423-cotter29 Bcast_1.c else { // Reformat info and print time and source ID recvline[n] = 0;/* null terminate */ now = ntohl((unsigned long)now);//put in host order now -= UNIXEPOCH;// convert UCT to UNIX epoch printf("%s", ctime(&now)); sadr = (struct sockaddr_in *)&reply_addr; printf("from %s: %s",inet_ntoa(sadr->sin_addr), ctime(&now)); }

30 cs423-cotter30 Bcast_1.c int errexit(const char *format,...) { va_listargs; va_start(args, format); vfprintf(stderr, format, args); va_end(args); exit(1); } static void recvfrom_alarm(int signo) { printf("Alarm was triggered\n"); /* just interrupt the recvfrom() */ }

31 cs423-cotter31 Summary Many other socket capabilities beyond basic client / server –Other library commands –Other ways to use select( ) –Poll( ) function –Broadcast capability –Etc.

Download ppt "Advanced Sockets in UNIX / Linux References: Internetworking with TCP/IP (Comer) (Linux / POSIX Sockets Version) UNIX Network Programming Vol. 1, 2ed.(Stevens)"

Similar presentations

Ads by Google