Navigationskarta Insitutitionen för Datavetenskap Umeå Universitet

Kodexempel F13



#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char **argv)
{
        int fd;
        char buff[1024], *fa;
        if ((fd = open(argv[1], O_RDONLY)) < 0) {
                perror(argv[1]);
                exit(1);
        }
        if ((fa = mmap(0, 1024, PROT_READ, MAP_PRIVATE, fd, 0)) == (caddr_t) -1) {
                perror("mmap() failed");
                exit(2);
        }
        if (memccpy(buff, fa, `\n', 1024) == NULL) {
                fprintf(stderr, "Line too long?\n");
                exit(3);
        }
        munmap(fa, 1024);
        printf("Here is the first line in %s:\n%s", argv[1], buff);
        return 0;
}


#include <sys/time.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); void FD_SET(int fd, fd_set *fdset); void FD_CLR(int fd, fd_set *fdset); int FD_ISSET(int fd, fd_set *fdset); void FD_ZERO(fd_set *fdset);
/* Enkelt exempel med en enda deskriptor (realtidsklocka på Linux-system). */ void await_frametime(int cfd) { fd_set readfds; int ticks=0; unsigned long n; struct timeval tout; while (ticks<NTICKS) { tout.tv_sec=3; tout.tv_usec=0; FD_ZERO(&readfds); FD_SET(cfd, &readfds); if (select(cfd+1, &readfds, NULL, NULL, &tout)==-1) diep("select"); if (!FD_ISSET(cfd, &readfds)) die("select() timed out!\n"); if (read(cfd, &n, sizeof(unsigned long))==-1) diep("read"); n>>=8; ticks+=n; } }
#include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int timeout); struct pollfd { int fd; short events; short revents; };
struct pollfd fds[2]; fds[0].fd=client1_fd; fds[0].events=POLLIN|POLLOUT; fds[1].fd=client2_fd; fds[1].events=POLLIN|POLLOUT; if (poll(fds, 2, -1) == -1) ... /* Fel */ if (fds[0].revents & POLLIN) ... /* Kan läsa från klient 1 */ if (fds[1].revents & POLLOUT) ... /* Kan skriva till klient 1 */
struct in_addr { /* netinet/in.h */ union { struct { uchar_t s_b1, s_b2, s_b3, s_b4; } _S_un_b; struct { ushort_t s_w1, s_w2; } _S_un_w; uint32_t _S_addr; } _S_un; }; struct hostent { /* netdb.h */ char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ }; struct sockaddr { /* sys/socket.h */ sa_family_t sa_family; /* address family */ char sa_data[14]; /* up to 14 bytes of direct address */ }; struct sockaddr_in { /* netinet/in.h */ sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; };

Detta är några av de struct-typer man arbetar med vid socket-programmering . Lägg märke till att sockaddr och sockaddr_in är lika stora. Det är för att man s ka kunna skicka vilken sorts sockel som helst till vissa funktioner. (Andra sorters socklar än Internet/Berkeley-socklar använder andra typer av struct:ar istället för sockaddr_in.)


#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>

struct in_addr *LookupHost(const char *hname)
{
  struct hostent *he;

  he = gethostbyname(hname);
  if (he == NULL) {
    fprintf(stderr, "DNS lookup failure for %s\n", hname);
    exit(1);
  }
  return ((struct in_addr *) (he->h_addr_list)[0]);
}

int main(void)
{
  struct in_addr *saddr;

  saddr = LookupHost("www.cs.umu.se");
  printf("Server address: %s\n", inet_ntoa(*saddr));
  return 0;
}

Det här programmet tar reda på den numeriska IP-adressen för www.cs.umu.se .


#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>

/* LookupHost goes here. Note that error checking has */
/* been omitted. Failure to check for errors in real  */
/* code will be punished severely.                    */

int main(void)
{
    struct in_addr *haddr;
    struct sockaddr_in saddr;
    int sock, n;
    char buf[256+1], *cmd = "GET / HTTP/1.0\n\n";

    haddr = LookupHost("www.cs.umu.se");
    printf("Server address: %s\n", inet_ntoa(*haddr));

    sock = socket(AF_INET, SOCK_STREAM, 0);
     memset(&saddr, 0, sizeof(saddr));
    memcpy(&saddr.sin_addr, haddr, sizeof(struct in_addr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(80);

    connect(sock, &saddr, sizeof(saddr));
    send(sock, cmd, strlen(cmd), 0);
    n = recv(sock, buf, 256, 0);
    buf[n] = '\0';
    puts(buf);
    close(sock);

    return 0;
}

Det här exemplet ansluter sig till www.cs.umu.se och läser (högst) 256 tec ken från indexsidan. När man kompilerar måste man ta med biblioteken nsl och xnet:

$ gcc -Wall -o ex2 ex2.c -lnsl -lxnet
...
$ ex2

int SetupSocket(void) { int sock; struct sockaddr_in host; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) ExitPerr("socket"); host.sin_addr.s_addr = INADDR_ANY; host.sin_port = htons(25000); host.sin_family = AF_INET; if (bind(sock, (struct sockaddr *) &host, sizeof(host)) != 0) ExitPerr("bind"); if (listen(sock, 5) != 0) ExitPerr("listen"); return sock; } int WaitConn(int sock, struct sockaddr_in *client) { int newsock; int addrlen = sizeof(struct sockaddr_in); puts("Waiting for connection..."); newsock = accept(sock, (struct sockaddr *) client, &addrlen); if (newsock == -1) ExitPerr("accept"); printf ("Connection accepted. Listener socket: %d. " "New socket: %d.\n", sock, newsock); printf("Client IP: %d.%d.%d.%d\n", (client->sin_addr).S_un.S_un_b.s_b1, (client->sin_addr).S_un.S_un_b.s_b2, (client->sin_addr).S_un.S_un_b.s_b3, (client->sin_addr).S_un.S_un_b.s_b4); return newsock; }

De här två funktionerna hann jag inte med på föreläsningen. De visar hur man sätter upp en lyssnarsockel, som andra kan ansluta sig till, och hur man tar emot anslutningar från en sådan. Eventuellt hinner vi med detta på en senare föreläsning. Lägg märke till det alternativa sättet att skaffa en strängrepresentation av den numeriska IP-adressen (de fyra raderna i slutet av WaitConn som är nästan lika). Detta är mycket klumpigare än inet_ntoa, men visar hur sin_addr-delen av en sockaddr_in är uppbyggd.

[an error occurred while processing this directive]