1 / 31

Advanced Sockets in UNIX / Linux

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). Addressing Support. getsockname (socket, name, namelen)

Download Presentation

Advanced Sockets in UNIX / Linux

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. 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. 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.

  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_t ai_addrlen; struct sockaddr * ai_addr; char * ai_cannonname; struct addrinfo * ai_next; }

  6. Send / recv Options 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 int alen; /* length of client's address */ int z; char buf[BUFSIZE]; switch (argc) { case 1: break; case 2: 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. 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. 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. 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); } } 14

  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); } 15

  16. 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 { int fd; //descriptor to check short events; //events of interest on fd short revents; //events that occurred on fd }

  17. Poll Events

  18. TCPpollechod.c #include <sys/types.h>,<sys/socket.h>,<sys/time.h>,<netinet/in.h> <unistd.h>,<string.h>,<stdio.h>,<asm/poll.h>,<asm/errno.h> #define QLEN 5 // maximum connection queue length #define BUFSIZE 4096 #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 int msock, connfd, sockfd; // master server socket struct pollfd client[MAX_OPEN]; unsigned int alen; // from-address length int fd, nfds, maxi, nready, i, n; socklen_t clilen; char line[BUFSIZE];

  19. TCPpollechod.c switch (argc) { case 1: break; case 2: 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;

  20. TCPpollechod.c while (1) { nready = poll(client, maxi +1, INFTIM); if (client[0].revents & POLLRDNORM)//new connect rqst? { clilen = sizeof(fsin); connfd = accept(msock, (struct sockaddr *) &fsin, &clilen); for (i = 1; i < MAX_OPEN; i++) if (client[i].fd < 0) { client[i].fd = connfd;//save descriptor break; } if (i == MAX_OPEN) errexit("too many clients"); client[i].events = POLLRDNORM; if (i > maxi) maxi = i; // max index in client[] array if (--nready <= 0) continue; // no more readable descriptors }

  21. 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. 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. 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. 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. 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. 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. 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_SOCKET IPPROTO_IPV6 • IPPROTO_TCP IPPROTO_ICMPV6 • IPPROTO_IP • opt = option selected • SO_BROADCAST SO_RCVBUF • SO_KEEPALIVE SO_RCVTIMEO • SO_OOBINLINE … • optval = address for value returned (void *) • optlen = length of option field (int *)

  28. 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. 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. Bcast_1.c int errexit(const char *format, ...) { va_list args; 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. Summary • Many other socket capabilities beyond basic client / server • Other library commands • Other ways to use select( ) • Poll( ) function • Broadcast capability • Etc.

More Related