📄 clientserver.html
字号:
<HTML><HEAD><TITLE>Client-Server Background</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.70"><LINKREL="HOME"TITLE="Beej's Guide to Network Programming"HREF="index.html"><LINKREL="PREVIOUS"TITLE="System Calls or Bust"HREF="syscalls.html"><LINKREL="NEXT"TITLE="Slightly Advanced Techniques"HREF="advanced.html"><METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=utf-8"></HEAD><BODYCLASS="sect1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Beej's Guide to Network Programming</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="syscalls.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="advanced.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="sect1"><H1CLASS="sect1"><ANAME="clientserver">5. Client-Server Background</A></H1><P>It's a client-server world, baby. Just about everything on thenetwork deals with client processes talking to server processes andvice-versa. Take <BCLASS="command">telnet</B>, for instance. When youconnect to a remote host on port 23 with telnet (the client), a programon that host (called <BCLASS="command">telnetd</B>, the server) springs tolife. It handles the incoming telnet connection, sets you up with alogin prompt, etc.</P><DIVCLASS="figure"><ANAME="figure2"></A><P><B>Figure 2. Client-Server Interaction.</B></P><DIVCLASS="mediaobject"><P><IMGSRC="cs.gif"ALT="[Client-Server Interaction Diagram]"></IMG></P></DIV></DIV><P>The exchange of information between client and server issummarized in <AHREF="clientserver.html#figure2">Figure 2</A>.</P><P>Note that the client-server pair can speak<TTCLASS="constant">SOCK_STREAM</TT>, <TTCLASS="constant">SOCK_DGRAM</TT>, oranything else (as long as they're speaking the same thing.) Some goodexamples of client-server pairs are<BCLASS="command">telnet</B>/<BCLASS="command">telnetd</B>,<BCLASS="command">ftp</B>/<BCLASS="command">ftpd</B>, or<BCLASS="command">bootp</B>/<BCLASS="command">bootpd</B>. Every time you use<BCLASS="command">ftp</B>, there's a remote program,<BCLASS="command">ftpd</B>, that serves you.</P><P>Often, there will only be one server on a machine, and that serverwill handle multiple clients using <TTCLASS="function">fork()</TT>. Thebasic routine is: server will wait for a connection,<TTCLASS="function">accept()</TT> it, and <TTCLASS="function">fork()</TT> achild process to handle it. This is what our sample server does in thenext section.</P><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="simpleserver">5.1. A Simple Stream Server</A></H2><P>All this server does is send the string "<TTCLASS="computeroutput">Hello,World!\n</TT>" out over a stream connection. All you needto do to test this server is run it in one window, and telnet to it fromanother with:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="screen"> <TTCLASS="prompt">$</TT> <BCLASS="command">telnet remotehostname 3490</B></PRE></TD></TR></TABLE><P>where <TTCLASS="computeroutput">remotehostname</TT> is the nameof the machine you're running it on.</P><P><AHREF="http://www.ecst.csuchico.edu/~beej/guide/net/examples/server.c"TARGET="_top">The server code</A>: (Note: atrailing backslash on a line means that the line is continued on thenext.)</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> /* ** server.c -- a stream socket server demo */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h> #define MYPORT 3490 // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue will hold void sigchld_handler(int s) { while(wait(NULL) > 0); } int main(void) { int sockfd, new_fd; // listen on sock_fd, new connection on new_fd struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connector's address information int sin_size; struct sigaction sa; int yes=1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } while(1) { // main accept() loop sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (!fork()) { // this is the child process close(sockfd); // child doesn't need the listener if (send(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); close(new_fd); exit(0); } close(new_fd); // parent doesn't need this } return 0; } </PRE></TD></TR></TABLE><P>In case you're curious, I have the code in one big<TTCLASS="function">main()</TT> function for (I feel) syntactic clarity.Feel free to split it into smaller functions if it makes you feelbetter.</P><P>(Also, this whole <TTCLASS="function">sigaction()</TT> thing might benew to you--that's ok. The code that's there is responsible for reapingzombie processes that appear as the <TTCLASS="function">fork()</TT>ed childprocesses exit. If you make lots of zombies and don't reap them, yoursystem administrator will become agitated.)</P><P>You can get the data from this server by using the clientlisted in the next section.</P></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="simpleclient">5.2. A Simple Stream Client</A></H2><P>This guy's even easier than the server. All this client does isconnect to the host you specify on the command line, port 3490. It getsthe string that the server sends.</P><P><AHREF="http://www.ecst.csuchico.edu/~beej/guide/net/examples/client.c"TARGET="_top">The clientsource</A>:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> /* ** client.c -- a stream socket client demo */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <netdb.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -