⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tyt14fi.htm

📁 一个学习tcp/ip协议的教程
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<HTML><HEAD><TITLE>tyt14fi.htm</TITLE><LINK REL=ToC HREF=index-1.htm><LINK REL=Index HREF=tppmsgs/msgs0.htm#37><LINK REL=Next HREF=tytxafi.htm><LINK REL=Previous HREF=tyt13fi.htm></HEAD><BODY BGCOLOR=#FFFFFF TEXT=#000000 LINK=#0000FF VLINK=#800080><A ID=I0 NAME=I0></A><P><P ALIGN=CENTER><A HREF=tyt13fi.htm TARGET=_self><IMG SRC=blanprev.gif WIDTH = 37 HEIGHT = 37 BORDER = 0 ALT="Previous Page"></A><A HREF=index-1.htm TARGET=_self><IMG SRC=blantoc.gif WIDTH = 37 HEIGHT = 37 BORDER = 0 ALT=TOC></A><A HREF=tytxafi.htm TARGET=_self><IMG SRC=blannext.gif WIDTH = 37 HEIGHT = 37 BORDER = 0 ALT="Next Page"></A><HR ALIGN=CENTER><P><UL><UL><UL><LI><A HREF=#E68E126>Development of the Socket Programming Interface</A></LI><LI><A HREF=#E68E127>Socket Services</A></LI><UL><LI><A HREF=#E69E178>Transmission Control Block</A></LI><LI><A HREF=#E69E179>Creating a Socket</A></LI><LI><A HREF=#E69E180>Binding the Socket</A></LI><LI><A HREF=#E69E181>Connecting to the Destination</A></LI><LI><A HREF=#E69E182>The open Command</A></LI><LI><A HREF=#E69E183>Sending Data</A></LI><LI><A HREF=#E69E184>Receiving Data</A></LI><LI><A HREF=#E69E185>Server Listening</A></LI><LI><A HREF=#E69E186>Getting Status Information</A></LI><LI><A HREF=#E69E187>Closing a Connection</A></LI><LI><A HREF=#E69E188>Aborting a Connection</A></LI><LI><A HREF=#E69E189>UNIX Forks</A></LI></UL><LI><A HREF=#E68E128>Summary</A></LI><LI><A HREF=#E68E129>Q&amp;A</A></LI><LI><A HREF=#E68E130>Quiz</A></LI></UL></UL></UL><HR ALIGN=CENTER><A ID=E66E14 NAME=E66E14></A><H1 ALIGN=CENTER><CENTER><FONT SIZE=6 COLOR=#FF0000><B>&#151; 14 &#151;</B><BR><B>The Socket Programming Interface</B></FONT></CENTER></H1><BR><P>Today I look at the last remaining aspect of TCP/IP this course covers: the socket interface for programming. This information is intended to convey the process needed to integrate an application with TCP/IP and as such involves some basic programming functions. It is not necessary to understand programming to understand this information. The functions involved in the socket programming interface help you understand the steps TCP/IP goes through when creating connections and sending data.<BR><P>Understanding the socket interface is helpful even if you never intend to write a line of TCP/IP code, because all the applications you will work with use these principles and procedures. Debugging or troubleshooting a problem is much easier when you understand what is going on behind the user interface. Today I don't attempt to show the complete socket interface. Instead I deal only with the primary functions necessary to create and maintain a connection. This chapter is not intended to be a programming guide, either.<BR><P>Because the original socket interface was developed for UNIX systems, today's text has a decidedly UNIX-based orientation. However, the same principles apply to most other operating systems that support TCP/IP.<BR><BR><A ID=E68E126 NAME=E68E126></A><H3 ALIGN=CENTER><CENTER><FONT SIZE=5 COLOR=#FF0000><B>Development of the Socket Programming Interface</B></FONT></CENTER></H3><BR><P>TCP/IP is fortunate because it has a well-defined application programming interface (API), which dictates how an application uses TCP/IP. This solves a basic problem that has occurred on many other communications protocols, which have several approaches to the same problem, each incompatible with the other. The TCP/IP API is portable (it works across all operating systems and hardware that support TCP/IP), language-independent (it doesn't matter which language you use to write the application), and relatively uncomplicated.<BR><P>The Socket API was developed at the University of California at Berkeley as part of their BSD 4.1c UNIX version. Since then the API has been modified and enhanced but still retains its BSD flavor. Not to be outdone, AT&amp;T (BSD's rival in the UNIX market) introduced the Transport Layer Interface (TLI) for TCP and several other protocols. One of the strengths of the Socket API and TLI is that they were not developed exclusively for TCP/IP but are intended for use with several communications protocols. The Socket interface remains the most widespread API in current use, although several newer interfaces are being developed.<BR><P>The basic structure of all socket programming commands lies with the unique structure of UNIX I/O. With UNIX, both input and output are treated as simple pipelines, where the input can be from anything and the output can go anywhere. The UNIX I/O system is sometimes referred to as the <I>open-read-write-close</I> system, because those are the steps that are performed for each I/O operation, whether it involves a file, a device, or a communications port.<BR><P>Whenever a file is involved, the UNIX operating system gives the file a <I>file descriptor, </I>a small number that uniquely identifies the file. A program can use this file descriptor to identify the file at any time. (The same holds true for a device; the process is the same.) A file operation uses an open function to return the file descriptor, which is used for the read (transfer data to the user's process) or write (transfer data from the user process to the file) functions, followed by a close function to terminate the file operation. The open function takes a filename as an argument. The read and write functions use the file descriptor number, the address of the buffer in which to read or write the information, and the number of bytes involved. The close function uses the file descriptor. The system is easy to use and simple to work with.<BR><P>TCP/IP uses the same idea, relying on numbers to uniquely identify an end point for communications (a socket). Whenever the socket number is used, the operating system can resolve the socket number to the physical connector. An essential difference between a file descriptor and a socket number is that the socket requires some functions to be performed prior to the establishment of the socket (such as initialization). In techno-speak, &quot;a file descriptor binds to a specific file or device when the open function is called, but the socket can be created without binding them to a specific destination at all (necessary for UDP), or bind them later (for TCP when the remote address is provided).&quot; The same open-read-write-close procedure is used with sockets.<BR><P>The process was actually used literally with the first versions of TCP/IP. A special file called /dev/tcp was used as the device driver. The complexity added by networking made this approach awkward, though, so a library of special functions (the API) was developed. The essential steps of open, read, write, and close are still followed in the protocol API.<BR><BR><A ID=E68E127 NAME=E68E127></A><H3 ALIGN=CENTER><CENTER><FONT SIZE=5 COLOR=#FF0000><B>Socket Services</B></FONT></CENTER></H3><BR><P>There are three types of socket interfaces defined in the TCP/IP API. A socket can be used for TCP <I>stream communications, </I>in which a connection between two machines is created. It can be used for <I>UDP datagram </I><I>communications,</I> a connectionless method of passing information between machines using packets of a predefined format. Or it can be used as a <I>raw</I> datagram process, in which the datagrams bypass the TCP/UDP layer and go straight to IP. The latter type arises from the fact that the socket API was not developed exclusively for TCP/IP.<BR><P>The presence of all three types of interfaces can lead to problems with some parameters that depend exclusively on the type of interface. You must always bear in mind whether TCP or UDP is used.<BR><P>There are six basic communications commands that the socket API addresses through the TCP layer:<BR><UL><LI>open: Establishes a socket<BR></LI><BR><LI>send: Sends data to the socket<BR></LI><BR><LI>receive: Receives data from a socket<BR></LI><BR><LI>status: Obtains status information about a socket<BR></LI><BR><LI>close: Terminates a connection<BR></LI><BR><LI>abort: Cancels an operation and terminates the connection<BR></LI><BR></UL><P>All six operations are logical and used as you would expect. The details for each step can be quite involved, but the basic operation remains the same. Many of the functions have been seen in previous days when dealing with specific protocols in some detail. Some of the functions (such as open) comprise several other functions that are available if necessary (such as establishing each end of the connection instead of both ends at once).<BR><P>Despite the formal definition of the functions within the API specifications, no formal method is given for how to implement them. There are two logical choices: synchronous, or <I>blocking,</I> in which the application waits for the command to complete before continuing execution; and asynchronous, or <I>nonblocking,</I> in which the application continues executing while the API function is processed. In the latter case, a function call further in the application's execution can check the API functions' success and return codes.<BR><P>The problem with the synchronous or blocking method is that the application must wait for the function call to complete. If timeouts are involved, this can cause a noticeable delay for the user.<BR><BR><A ID=E69E178 NAME=E69E178></A><H4 ALIGN=CENTER><CENTER><FONT SIZE=4 COLOR=#FF0000><B>Transmission Control Block</B></FONT></CENTER></H4><BR><P>The Transmission Control Block (TCB) is a complex data structure that contains details about a connection. The full TCB has over fifty fields in it. The exact layout and contents of the TCB are not necessary for today's material, but the existence of the TCB and the nature of the information it holds are key to the behavior of the socket interface.<BR><BR><A ID=E69E179 NAME=E69E179></A><H4 ALIGN=CENTER><CENTER><FONT SIZE=4 COLOR=#FF0000><B>Creating a Socket</B></FONT></CENTER></H4><BR><P>The API lets a user create a socket whenever necessary with a simple function call. The function requires the family of the protocol to be used with the socket (so the operating system knows which type of socket to assign and how to decode information), the type of communication required, and the specific protocol. Such a function call is written as follows:<BR><BR><PRE><FONT COLOR=#000080>socket(<I>family</I>, <I>type</I>, <I>protocol</I>)</FONT></PRE><P>The <I>family</I> of the protocol actually specifies how the addresses are interpreted. Examples of families are TCP/IP (coded as AF_INET), Apple's AppleTalk (AF_APPLETALK), and UNIX filesystems (AF_UNIX). The exact protocol within the family is specified as the protocol parameter. When used, it specifically indicates the type of service that is to be used.<BR><P>The <I>type</I> parameter indicates the type of communications used. It can be a connectionless datagram service (coded as SOCK_DGRAM), a stream delivery service (SOCK_STREAM), or a raw type (SOCK_RAW). The result from the function call is an integer that can be assigned to a variable for further checking.<BR><BR><A ID=E69E180 NAME=E69E180></A><H4 ALIGN=CENTER><CENTER><FONT SIZE=4 COLOR=#FF0000><B>Binding the Socket</B></FONT></CENTER></H4><BR><P>Because a socket can be created without any binding to an address, there must be a function call to complete this process and establish the full connection. With the TCP/IP protocol, the socket function does not supply the local port number, the destination port, or the IP address of the destination. The bind function is called to establish the local port address for the connection.<BR><P>Some applications (especially on a server) want to use a specific port for a connection. Other applications are content to let the protocol software assign a port. A specific port can be requested in the bind function. If it is available, the software allocates it and returns the port information. If the port cannot be allocated (it might be in use), a return code indicates an error in port assignment.<BR><P>The bind function has the following format:<BR><BR><PRE><FONT COLOR=#000080>bind(<I>socket</I>, <I>local_address</I>, <I>address_length</I>)</FONT></PRE><P><I>socket</I> is the integer number of the socket to which the bind is completed; <I>local_address</I> is the local address to which the bind is performed; and <I>address_length</I> is an integer that gives the length of the address in bytes. The address is not returned as a simple number but has the structure shown in Figure 14.1.<BR><P><B><A HREF=14tyt01.gif>Figure 14.1. Address structure used by the socket </B><B>API.</A></B><BR><P>The address data structure (which is called usually called sockaddr for <I>socket address</I>) has a 16-bit Address Family field that identifies the protocol family of the address. The entry in this field determines the format of the address in the following field (which might contain other information than the address, depending on how the protocol has defined the field). The Address field can be up to 14 bytes in length, although most protocols do not need this amount of space.<BR><BLOCKQUOTE><BLOCKQUOTE><HR ALIGN=CENTER><BR><NOTE><IMG SRC=note.gif WIDTH = 75 HEIGHT = 46>The use of a data structure instead of a simple address has its roots in the UNIX operating system and the closely allied C programming language. The formal structure of the socket address enables C programs to use a union of structures for all possible address families. This saves a considerable amount of coding in applications.</NOTE><BR><HR ALIGN=CENTER></BLOCKQUOTE></BLOCKQUOTE><P>TCP/IP has a family address of 2, following which the Address field contains both a protocol port number (16 bits) and the IP address (32 bits). The remaining eight bytes are unused. This is shown in Figure 14.2. Because the address family defines how the Address field is decoded, there should be no problem with TCP/IP applications understanding the two pieces of information in the Address field.<BR><P><B><A HREF=14tyt02.gif>Figure 14.2. The address structure for TCP/IP.</A></B><BR><BR><A ID=E69E181 NAME=E69E181></A><H4 ALIGN=CENTER><CENTER><FONT SIZE=4 COLOR=#FF0000><B>Connecting to the Destination</B></FONT></CENTER></H4><BR><P>After a local socket address and port number have been assigned, the destination socket can be connected. A one-ended connection is referred to as being in an <I>unconnected state, </I>whereas a two-ended (complete) connection is in a <I>connected state.</I> After a bind function, an unconnected state exists. To become connected, the destination socket must be added to complete the connection.<BR><BLOCKQUOTE><BLOCKQUOTE><HR ALIGN=CENTER><BR><NOTE><IMG SRC=note.gif WIDTH = 75 HEIGHT = 46>Connectionless protocols such as UDP do not require a connected state to function. They can, however, be connected to enable transfer between the two sockets without having to specify the destination address each time. Connection-based protocols such as TCP require both ends of the connection to be specified.</NOTE><BR><HR ALIGN=CENTER></BLOCKQUOTE></BLOCKQUOTE><P>To establish a connection to a remote socket, the connect function is used. The connect function's format is<BR><BR><PRE><FONT COLOR=#000080>connect(<I>socket</I>, <I>destination_address</I>, <I>address_length</I>)</FONT></PRE><P>The <I>socket</I> is the integer number of the socket to which to connect; the <I>destination_address</I> is the socket address data structure for the destination address (using the same format as shown in Figure 14.1); and the <I>address_length</I> is the length of the destination address in bytes.<BR><P>The manner in which connect functions is protocol-dependent. For TCP, connect establishes the connection between the two endpoints and returns the information about the remote socket to the application. If a connection can't be established, an error message is generated. For a connectionless protocol such as UDP, the connect function is still necessary but stores only the destination address for the application.<BR><BR><A ID=E69E182 NAME=E69E182></A><H4 ALIGN=CENTER><CENTER><FONT SIZE=4 COLOR=#FF0000><B>The </B><B><I>open</I></B><B> Command</B></FONT></CENTER></H4><BR><P>The open command prepares a communications port for communications. This is an alternative to the combination of the functions shown previously, used by applications for specific purposes. There are really three kinds of open commands, two of which set a server to receive incoming requests and the third used by a client to initiate a request. With every open command, a TCB is created for that connection.<BR><P>The three open commands are an unspecified passive open (which enables a server to wait for a connection request from any client), a fully specified passive open (which enables a server to wait for a connection request from a specific client), and an active open (which initiates a connection with a server). The input and output expected from each command are shown in Table 14.1.<BR><BR><P ALIGN=CENTER><CENTER><FONT COLOR=#000080><B>Table 14.1. Open command parameters.</B></FONT></CENTER><BR><CENTER><TABLE BORDERCOLOR=#000040 BORDER=1 CELLSPACING=2 CELLPADDING=3><TR><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P><B><I>Type</I></B></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P><B><I>Input</I></B></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P><B><I>Output</I></B></FONT><TR><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>Unspecified<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local port<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local connection name<BR></FONT><TR><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>passive open<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>Optional: timeout, precedence, security, maximum segment size<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local connection name<BR></FONT><TR><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>Fully specified passive open<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local port, remote IP address, remote port Optional: timeout, precedence, security, maximum segment size<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local connection name<BR></FONT><TR><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>Active open<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local port, destination IP address, destination port Optional: timeout, precedence, security, maximum segment size<BR></FONT><TD BGCOLOR=#80FFFF><FONT COLOR=#000080><P>local connection name</FONT></TABLE></CENTER><BR><P>When an open command is issued by an application, a set of functions within the socket interface is executed to set up the TCB, initiate the socket number, and establish preliminary values for the variables used in the TCB and the application.<BR><P>The passive open command is issued by a server to wait for incoming requests. With the TCP (connection-based) protocol, the passive open issues the following function calls:<BR><UL><LI>socket: Creates the sockets and identifies the type of communications.<BR></LI><BR><LI>bind: Establishes the server socket for the connection.<BR></LI><BR><LI>listen: Establishes a client queue.<BR></LI><BR><LI>accept: Waits for incoming connection requests on the socket.<BR></LI><BR></UL><P>The active open command is issued by a client. For TCP, it issues two functions:<BR><UL><LI>socket: Creates the socket and identifies the communications type.<BR></LI><BR><LI>connect: Identifies the server's IP address and port; attempts to establish communications.<BR></LI><BR></UL><P>If the exact port to use is specified as part of the open command, a bind function call replaces the connect function.<BR><BR><A ID=E69E183 NAME=E69E183></A><H4 ALIGN=CENTER><CENTER><FONT SIZE=4 COLOR=#FF0000><B>Sending Data</B></FONT></CENTER></H4><BR><P>There are five functions within the Socket API for sending data through a socket. These are send, sendto, sendmsg, write, and writev. Not surprisingly, all these functions send data from the application to TCP. They do this through a buffer created by the application (for example, it might be a memory address or a character string), passing the entire buffer to TCP. The send, write, and writev functions work only with a connected socket because they have no provision to specify a destination address within their function call.<BR><P>The format of the send function is simple. It takes the local socket connection number, the buffer address for the message to be sent, the length of the message in bytes, a Push flag, and an Urgent flag as parameters. An optional timeout might be specified. Nothing is returned as output from the send function. The format is<BR><BR><PRE><FONT COLOR=#000080>send(<I>socket</I>, <I>buffer_address</I>, <I>length, flags</I>)</FONT></PRE><P>The sendto and sendmsg functions are similar except they enable an application to send a message through an unconnected socket. They both require the destination address as part of their function call. The sendmsg function is simpler in format than the sendto function, primarily because another data structure is used to hold information. The sendmsg function is often used when the format of the sendto function would be awkward and inefficient in the application's code. Their formats are<BR><PRE><FONT COLOR=#000080>sendto(<I>socket</I>, <I>buffer</I>_<I>address</I>, <I>length</I>, <I>flags</I>, <I>destination</I>, <I>address</I>_<I>length</I>)sendmsg(<I>socket</I>, <I>message</I>_<I>structure</I>, <I>flags</I>)</FONT></PRE><P>The last two parameters in the sendto function are the destination address and the length of the destination address. The address is specified using the format shown in Figure 14.1. The <I>message_structure</I> of the sendmsg function contains the information left out of the sendto function call. The format of the message structure is shown in Figure 14.3.<BR><P><B><A HREF=14tyt03.gif>Figure 14.3. The message structure used by </B><B>sendmsg</B><B>.</A></B><BR><P>The fields in the sendmsg message structure give the socket address, size of the socket address, a pointer to the iovector, which contains information about the message to be sent, the length of the iovector, the destination address, and the length of the destination address.<BR><BLOCKQUOTE><BLOCKQUOTE><HR ALIGN=CENTER><BR><NOTE><IMG SRC=note.gif WIDTH = 75 HEIGHT = 46>The sendmsg function uses the message structure to simplify the function call. It also has another advantage: the recvmsg function uses the same structure, simplifying an application's code.</NOTE><BR><HR ALIGN=CENTER></BLOCKQUOTE></BLOCKQUOTE><P>The iovector is an address for an array that points to the message to be sent. The array is a set of pointers to the bytes that comprise the message. The format of the iovector is simple. For each 32-bit address to a memory location with a chunk of the message, a corresponding 32-bit field holds the length of the message in that memory location. This format is repeated until the entire message is specified. This is shown in Figure 14.4. The iovector format enables a noncontiguous message to be sent. In other words, the first part of the message can be in one location in memory, and the rest is separated by other information. This can be useful because it saves the application from copying long messages into a contiguous location.<BR><P><B><A HREF=14tyt04.gif>Figure 14.4. The </B><B>iovector</B><B> format.</A></B><BR><P>The write function takes three arguments: the socket number, the buffer address of the message to be sent, and the length of the message to send. The format of the function call is<BR><BR><PRE><FONT COLOR=#000080>write(<I>socket</I>, <I>buffer_address</I>, <I>length</I>)</FONT></PRE><P>The writev function is similar to write except it uses the iovector to hold the message. This lets it send a message without copying it into another memory address. The format of writev is<BR><BR><PRE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -