Berkeley socket
6.1 Introduction
The network program design relies on the socket acceptance and sending information, although the word of the socket seems to be some mysterious, but
In fact, this concept is very easy to understand.
This chapter mainly tells the Sockets API (Application Program Interface), as well as some other details (ratio
Such as the history of socket, the common structure in the data, etc.), through these introductions, make the reader slowly mastered the socket under Linux
Program.
6.2 Overview
Before you begin to introduce your knowledge about programming, let us know some background knowledge related to Socket.
6.2.1 History of Socket
In the early 1980s, Advanced Research Provincial Agency, ARPA was funded.
A study group in Berkeley, University of Jiali Fun, let them transplant TCP / IP software to UNIX operating system
In, and provide the results to other outlets. As part of the project, the designers have created an interface and application process.
Use this interface to be convenient to communicate. They decided that as long as it is possible to use some system calls,
Some of the cases that cannot be easily entered into the existing function set, add new system calls to support TCP / IP functions.
The result of this appears, the Berkeley Socket, this system is called Berkeley UNIX
Or BSD UNIX. (TCP / IP appears in BSD 4.1 version Release 4.1 of Berkeley Software
Distribution.
Berkeley UNIX is used by many computer vendors, so many machines can be used.
In this way, the Socket interface is widely used, and it has now become the actual standard. (Figure 6-1)
6.2.2 Socket function
Socket English is the "hole" or "socket", now, as the process of process communication, the BSD UNIX,
Take the following sense. Some common sockets in daily life, some are signal sockets, some are power outlets, some can
Accept signal (or energy), some can send signals (or energy). If a telephone line is placed between a telephone?
The seat (equivalent to the interface between the two), this part of the device is physically existing), Socket is very similar to the telephone plug.
seat.
Compared with the connection-oriented Socket mechanism, there is an amazing place. With a national electricity
The voice is an example. Telephone calls are equivalent to two processes that communicate with each other; the area where the call is located (one
The global unique area code is equivalent to a network, the area code is its network address; the switch in the area is quite
At a host, the host assigns the internal number of each user equivalent to the Socket number (hereinafter referred to below).
Chapter 6 Berkeley Socket - 137 -
Figure 6-1 Socket Interface Schematic
Any user must first occupy a telephone before the call, which is equivalent to an Socket number;
The other party's phone number is equivalent to having a socket. Then dial the call to the other party, which is equivalent to sending a connection.
See if the other party is not in the same area, but also dial the other number, which is equivalent to give the network address). The other party is in the field
Idle (which is equivalent to the other host boot and accepts the connection request), pick up the phone microphone, and the two sides can formally talk, which is equivalent to success. The process of calling between the two parties is to send signals to the telephone and accept signal from the phone.
Process, equivalent to sending data to Socket and accepting data from Socket. After the call is over, one party hangs a telephone.
Equipate to close the socket, undo the connection.
In the telephone system, general users can only feel the presence of local telephones and other phone numbers, and establish calls.
Process, the process of voice transmission and the technical details of the entire telephone system are transparent, this is also related to the Socket mechanism.
very similar. Socket uses Internet network communication facilities to implement process communication, but it doesn't care about the details of communication facilities.
As long as the communication facilities provide sufficient communication capabilities, it is satisfied.
At this point, we have an intuitive description of Socket. Abstract, Socket essentially provides process communication
Endpoint. Before the process communication, both sides must first create an endpoint, otherwise there is no way to establish contacts and mutual
Communicate. As before calling, both sides must each have a telephone.
Every Socket is described in one and a semi-associated description:
{Protocol, local address, local port}
A complete Socket uses a related description
{Protocol, local address, local port, remote address, remote port}
Each socket has a local unique socket number, allocated by the operating system.
Most importantly, Socket is designed for customers-server models, providing customers and server programs
Different Socket systems calls. Customers apply for a Socket number (equivalent to a person who wants to call
- 138 - Linux network programming
Any call call on the phone is called; the server has a global recognized socket, any customer can go to it.
Send a connection request and information request (equivalent to a call from a call that has a call from the phone number known.
Socket uses the customer-server mode cleverly solves the problem between the process to establish a communication connection between the process. server
Socket is very important for global. Two completely random user processes because there is no side of Socket
It is fixed, just like the phone does not know the phone number of others, it is impossible to call.
6.2.3 Three types of sockets
There are three types of socket: stream socket (socket_stream), data sets (SOCK_DGRAM)
And original socket.
1. Flow socket (SOCK_STREAM)
Flow sockets can provide reliable,-facing communication flow. If you send it through the flow socket
Order data: "1", "2". Then the order of the data arrives at the distance is also "1", "2".
What can streaming? Have you heard Telnet applications? Have you heard? Oh, the most commonly used BBS service
The remote landing of the system is connected through the Telnet protocol. Telnet is a streaming connection. Do you
I hope that the characters (or Chinese characters) entered on the Telnet app are entered when they arrive at the remote application.
The order arrives? The answer should be sure. There is also a WWW browser that also uses the HTTP protocol through
Flow sockets to get web pages. In fact, if you telnet to the 80 port of a web site, then lose
Enter "GET webpage name" and press two to enter the bus (or two down Ctrl Enter) and you get the webpage represented by "Web path name"!
How does streaming socket guarantees data transmission quality in this application level? It uses TCP (the
The Transmission Control Protocol) protocol (you can refer to RFC-793 to get the details of TCP). TCP guarantee
Your data transfer is correct and is the order. TCP is the first half of the TCP / IP that occurs. IP
On behalf of Internet Protocol (Internet Protocol, Reference RFC-791) IP only processes network routing.
Chapter 6 Berkeley Socket - 139 -
Figure 6-2 Workflow for connecting Socket
2. Data Report (SOCK_DGRAM)
Data report sets define a connectionless service, data is transmitted through independent packets, is disorder
And not guaranteed reliability, no error. Original socket allows direct access to low-level protocols such as IP or ICMP, mainly
Tests for new network protocol implementations, etc.
What is Data Support Set (DataGram Sockets)? Why is it called "no connection"? What should I do?
What about them? Why is they unreliable? Ok, there are some facts here:
l If you send a datagram, it may not arrive.
l It may arrive in different order.
l If it arrives, there may be an error in the data it contains.
Data report is also used by IP, but it does not use TCP, it uses the user datagram protocol UDP (user
DataGram protocol can refer to RFC 768)
Why is they "no connection"? Because it (UDP) is not maintained as a flow socket
- 140 - Linux network programming
Connection, you only need to put the data into a package, put the remote IP, then send this package out. This one
The process does not need to be established. Applications of UDP include: TFTP, Bootp, etc.
So, since the packet will be lost, how can the program work properly? In fact, each UDP is used
The programs must have their own protocols that confirm the data. For example, the TFTP protocol defines the send out for each
Go to the packet, the remote is accepted back to a packet to tell the local program: "I have already got it!" (1
"ACK" package). If the delivery of the data package is not responded within 5 seconds, it will resend this
The data package is until the packet recipient returns the "ACK" signal. These knowledge is written in writing a UDP protocol
Programmers are very necessary.
Unconnected servers are generally for transaction-oriented, a response to a response completes the client program and service
The interaction between the program. If you use a connectionless socket programming, the process can be represented by Figure 6-3.
Figure 6-3 Unconnected Socket workflow
Request for connection server processing is often more complicated, not a request to answer, and
And it is often a concurrent server. Using a connection-oriented socket programming can be represented by Figure 6-2.
The socket work process is as follows: The server starts first, build a socket by calling socket (), then call
Bind () links the socket with the local network address, then call listen () to make the socket ready for listening,
And specify its length of request queue, then call accept () to receive the connection. Customers can call Connect () and servers to establish a connection after establishing a socket. Once the connection is established, the client and server can pass ()
And Write () to send and receive data. Finally, after the data is transmitted, the two parties call close () shut down socket.
3. Original socket
The original socket is mainly used for some of the development of protocols, which can compare the underlying operation. It is powerful, but
There is no convenient use of the two sockets described above, and the general procedures also involve the original socket.
Chapter 6 Berkeley Socket - 141 -
6.3 Linux dominated network protocol
The network protocol is the interface between the system and inter-system communication. On Linux system, TCP / IP
(Transmission Control / Internet Protocol) is the most common. TCP / IP is a network protocol protocol,
We will be described in detail below.
6.3.1 What is TCP / IP?
In a brief speaking, TCP / IP is the name of a network protocol, and the protocol is that all software products must be observed.
In order to ensure the rules that a variety of software products can correctly communicate. The agreement also defines how each part of the data block management
The data transmitted.
It is precisely that an agreement defines two applications or computers to communicate with each other.
Each of these (applications or computers) guarantees the same standard. TCP / IP Representative Transfer Control Protocol /
Network Agreement (Note: They are two different protocols!), It is designed as a network component component for software. each
TCP / IP protocols have their special work, such as the World Wide Web (WWW), send email (E-mail), biography
Transport (FTP), providing remote login services, etc.
The TCP / IP protocol can be divided into groups according to different services provided:
1. Control data protocol
TCP (Transmission Control Protocol Transmission Control Protocol) is based on the connection, that is, two computers
A connection must be created first before you can transfer data. In fact, the send and acceptable computer must always communicate with each other.
And contact.
UDP (User Data Protocol USER DATAGRAM Protocol) It is a connectionless service, data can be straight
Pick up and do not have to create a network connection between the two computers. It compared to the connected TCP, the occupancy band is small,
But you don't know if your data truly reach your client, and the data received by the client does not know if it is still
It is the original transmission order.
2. Data routing protocol
Routing protocols analyze the address of the packet and determine the transfer of data to the optimal route of the computer. They can also put big
The data is divided into several parts and combines them again in the destination.
IP (Internet Protocol Internet Protocol) Proactive actually transmits data.
ICMP (Internet Control Information Protocol Internet Control Message Protocol) Processes the status information of IP,
For example, data errors or changes that can affect routing decisions.
Rip (Routing Information Protocol Routing Information Protocol) It is the best route for several decision information transfer
One of the route protocols.
OSPF (Open Shortest Path First) A protocol used to determine the route. Network address protocol determines naming
Method of computer addresses: Use a unique number and a letter name.
ARP (Address Rode ADRESS Resolution Protocol) Determines the digital address of a computer on the network. DNS (Domain Name Domain Name System) determines the digital address of a machine from the name of the machine.
RARP (Reverse Address Determrance REVERSE Address Resolution Protocol) Determines a calculation on the network
The address of the machine, and the ARP (Address Decision Protocol Address Resolution Protocol) is just the opposite.
3. User service
Bootp (Start Protocol Boot Protocol) gets the startup information on the web server, then local network
- 142 - Linux network programming
The computer is started.
FTP (File Transfer Protocol File Transfer Protocol) transmits one from a computer via the International Interconnection Network
Or multiple files to another computer.
Telnet (remote login) allows a remote login, users can pass a machine from a network through Telnet
Connect to another machine, just like the user directly in the local operation.
EGP (External Gateway Protocol EXTERIOR GATEWAY Protocol) provides routing information for external network.
GGP (Gateway to Gateway Protocol Gateway-to-Gateway Protocol) Transmission Road between Gateway and Gateway
.
IGP (Internal Gateway Protocol Interior Gateway Protocol) traffic route information in internal network.
3. Other agreements (also provide an important service for the network)
NFS (Network File System Network File System) Allows the directory of a machine by another machine
User installation (MOUNT) is onto your own machine, just like the local file system is working all kinds
Operation.
NIS (Network Information Service Network Information Service) to the username, password of the entire network user
Unified management, simplify the username / password checking of the entire network under NIS service.
RPC (Remote Procedure Call Remote Procedure Call) passes it allows remote applications to be simplified
Single, effective means to contact the local application, and vice versa.
SMTP (Simple Mail Protocol Simple Mail Transfer Protocol) A specially for email in multiple
The protocol transmitted in the machine, the inevitable service provided by the SMTP server of the mail.
SNMP (Simple Network Management Protocol Simple Network Management Protocol) This is a super-use
The service prepared by the household, super users can make simple network management.
6.4 socket address
Ok, about the background knowledge of Socket we have already spent enough, let us officially start unveiling socket
Mysterious veil!
6.4.1 What is Socket?
Everyone often talks about "socket" (socket), then what is a socket?
A socket can be explained like this: it is communication through standard UNIX file descriptors and other programmakers.
A method.
6.4.2 Socket Descriptor
There is such a sentence using UNIX hacker masters: "Well, in the UNIX system, everything is a text.
Part. "This sentence describes the fact that in the UNIX system, any of the operations for I / O is achieved by reading or writing a file descriptor.
A file descriptor is just a simple plastic value, representing an open file (here the file is wide)
The file does not only represent different disk files, which can represent a connection on a network, an advanced first out of the team
Columns, a terminal display screen, and everything else). Anything in the UNIX system is a file! ! Instant
For if you want to communicate with another program, you will be described by a file.
of. You better believe this.
Chapter 6 Berkeley Socket - 143 -
Ok, you have already believed that Socket is a file descriptor, then how should we get this representative?
What about the file descriptor of the network connection? You must now be very concerned about this problem. This is the case: You first call the system letter
Number socket (), it returns a socket descriptor, then you can describe this socket descriptor
Make some operations: system function send () and rec () (you can use the "man" command to find system help: Man
Send, Man Recv.
You will want: "The socket descriptor is a file descriptor why can't use Write () and
Read () to make a socket communication? "In fact, Write () and read () can be operated on the socket descriptor
What you do, however, by using the Send () and RECV () functions, you can perform better control over the transmission of network data!
6.4.3 How is a socket transferred data on the network?
We have already talked about the network protocol layer, then we should continue to know more about something: the number of physical networks
It is transmitted.
We can think that it is like this:
Data is divided into a packet, the packet's data header (or data tail) is first protocol (such as TFTP)
Agreement) Plus the first layer protocol data; then the entire package (including the TFTP information headed inside) is then re-following
Second packaging (such as UDP), then this will then be packaged by the underlying protocol (such as an IP protocol), and finally
The last level of hardware layer (physical layer) package is on the last layer information (Ethernet information header).
When the receiving end computer receives this package, the hardware first strips the Ethernet information head in the packet, then
The kernel is stripped down the IP and UDP information header, and finally submits the packet to the TFTP application, stripped by TFTP TFTP
Information header, finally obtained raw data.
Below we will roughly review the famous network hierarchy model.
Through this network model, you can write a set of applications and don't care about the fact that the data is in the physical layer.
Transmission methods (whether Ethernet, or parallel port, AUI or other methods).
Because there have been programs to handle these problems at the bottom. Below is an OSI model, you can remember it
Pay some test.
l application layer
l representing a layer
l session layer
l transport layer
l network layer
l data link layer
l Physical layer
The physical layer is the hardware layer (such as parallel port, Ethernet). The application layer is far from the physical layer, so that it
Can not be affected by the physical layer.
The above model is the most common model, but in Linux, the model that is really used is the following: L Application layer (Telnet, FTP, etc.)
l Main intermite dialogue (TCP and UDP)
l Network layer (IP and routing)
l Network underlayer (equivalent to the network, data link and physical layer) in the OSI model)
Now, you have probably understand how each protocol layer packs and disubperes raw data. Observe
- 144 - Linux network programming
How many jobs do you have to do every packet? Correct! You need to use "cat" life for each packet.
Let's check the protocol information head!
just kidding. It is just to call the send () function to send data just to call the Send () function. For data
Online setup, you need to add a message head, then call the sendto () function to send the data. Linux system
Transport Layer and Internet Layer have been established in the kernel. Hardware is responsible for NetWorkAccess Layer. simple
Effective, isn't it?
Some basic knowledge of 6.5 socket
Ok, from now on, we should talk about things related to the program.
6.5.1 Basic Structure
First, I want to introduce some of the network data structures commonly used in the programming programming to be helpful to everyone.
1. Struct SockAddr
This structure is used to store socket addresses.
Data definition:
Struct sockaddr {
Unsigned short sa_family; / * address family, AF_XXX * /
Char SA_DATA [14]; / * 14 BYTES's protocol address * /
}
SA_FAMILY is generally "Afinet".
SA_DATA contains some of the number of remote computers, ports, and sockets, and the data inside it is melled in one.
Sliced.
In order to deal with Struct SockAddr, the programmer has established another similar structure STRUCT SOCKADDR_IN:
Struct SockAddr_in ("in" represents "Internet")
Struct sockaddr_in {
Short int SIN_FAMILY; / * Internet Address End * /
UNSIGNED short int sin_port; / * port number * /
Struct in_addr sin_addr; / * Internet Address * /
Unsigned char sin_zero [8]; / * Add 0 (size as Struct SockAddr) * /
}
This structure provides convenient means to access each element in the Socket Address (Struct SockAddr) structure.
. Note SIN_ZERO [8] is to be the same size in the memory, when using sockaddr_in
Want SIN_ZERO is all set to zero (use Bzero () or MEMSET () functions). Moreover, it is very important,
It is a pointer to Struct SockAddr_in to declare the structure of a Sturct SockAddr. So though
Socket () function requires a structaddr *, you can also give him a sockaddr_in *. Note in Struct
In SOCKADDR_IN, SIN_FAMILY is equivalent to SA_FAMILY in Struct SockAddr, you need to set "AF_Inet".
Finally, you must ensure that SIN_PORT and SIN_ADDR must be a network byte order (see next)! 2. Struct in_addr
It is defined as follows:
/ * Internet address (A structure for histical reasons) * /
Chapter 6 Berkeley Socket - 145 -
Struct in_addr {
Unsigned long s_addr;
}
If you declare a "INA" as a structure of Struct SockAddr_in, then
"INA.SIN_ADDR.S_ADDR" is the 4-byte IP address (discharged in network byte order). have to be aware of is,
Even if your system still uses the combination rather than the structure, you can still use the above method.
To 4 bytes of IP addresses (some #defines helped your busy).
6.5.2 Basic Conversion Function
The network byte order is mentioned earlier. So what is the network byte order, what is special, and how
What is the data we usually convert into this format?
1. Network byte order
Because each machine is different from the parable storage order of the variable (some system is in front, the bottom is behind,
Some systems are the bottom in front, high in the high position), and the data transmitted by the network is a certain order. and so
For a machine that represents the order and network byte order of internal byte, it must be converted to data (such as IP)
The representation of the address, the representation of the port number). But what should I do if the internal byte sequence and the network byte order are the same?
This is the case: they also call the conversion function, but true conversion is still determined by the system functions.
2. Conversion function
We usually use two data types: short (two bytes) and long (four bytes). Below
These conversion functions can perform correct conversion for these two types of unsigned integer variables.
If you want to convert a short data from the host byte order to the network byte order, there is such a letter.
Number: It is started with "H" (representing "host"); keeping it is "to", representing "transition to"; then "N"
Representing "Network"; finally "S", representing "Short Data". H-to-n-s is htons () function (you can use Host)
To NetWork Short to help
Very simple?? I don't understand this function is not good.?
You can use "n", "h", "to", "s", "L" any combination? Of course, you have to
Combine. For example, the system does not have a STOLH () function (Short to Long Host?).
A list of jacket byte conversion programs below:
l htons () - "Host to NetWork Short" host byte sequence is converted to network byte order (for unsigned
Short operation 4 bytes)
l HTONL () - "Host to NetWork Long" host byte sequence is translated into network byte sequence (pair no argument
Dimensions Operation 8 Bytes)
l NTOHS () - "Network to host short" network byte sequence to host byte order (no harmony
Number of short-type operation 4 bytes)
l NTOHL () - "NetWork to Host Long" network byte sequence is translated to host byte order (operation of unsigned long-signed long-term 8 bytes)
Note: Now you may think that you have been finered in these functions. You may think: "Well ?? in my 68000
Interior of the machine, the order of the byte is already the order of network bytes, then I don't have to call HTONL () in my program to convert my IP.
Some. Yes, you may be right. But if you transplant your program to an internal byte order and network byte sequence
On your program, your program will run! So, be sure to remember: Before you send the data to the Internet, you must put it on the word.
- 146 - Linux network programming
Sequential sequence transitions from host byte order to network byte order!
Sin_addr and sin_port in Struct SockAddr_in their byte order is the network byte order, and
SIN_FAMILY is not a network byte order. why?
This is because sin_addr and sin_port are data taken from IP and UDP protocols, and in IP and UDP
The protocol layer is related to the network, so they must use the network byte order. However, SIN_FAMILY field
Just use the kernel to determine that struct sockaddr_in is what type of data stored, and SIN_FAMIL is always
Will not be sent to the network, so you can store the host byte order.
3. IP address conversion
Very lucky, Linux system provides a function of using many functions for converting IP addresses, so you don't have to write a section
The labor-free subroutine to try to change IP.
First, let me assume that you have a struct sockaddr_in ina, and your IP is 166.111.69.52, you want
Store your IP to INA. You can use the function: INET_ADDR (), it can use a number and point table
String of the IP address is converted into an unsigned long integer. You can use it like this:
INA.SIN_ADDR.S_ADDR = INET_ADDR ("166.111.69.52");
note:
l inet_addr () The address returned is already the network byte order, you don't have to call the htonl () function, is it very
Convenient?
l The above usage is not a good habit, because the above code does not have an error check. If the inet_addr () function
Execute an error, it will return -1 ??, etc.! Binary unsigned integer value - 1 is equivalent? Equivalent to 255.255.255.255 !!
A broadcast IP address! There is no way, you can only check the mistakes of the disease in your own program.
Ok, now we can already convert the IP address of the string to growth. So there is any other method
? If you have a struct in_addr and you want to print it from the IP address represented (according to numbers.).
Word. Digital format)??
Here you can use the function inet_ntoa () ("NTOA" representative "NetWork to ASCII"):
Printf ("% s", inet_ntoa (INA.SIN_ADDR);
This code will use the network address stored in Struct in_addr to digital. Number. Number. Digital.
It is shown.
note:
l INET_NTOA () uses struct in_addr as a parameter, not a long integer value. l INET_NTOA () Returns a character pointer, pointing to a Static Type String defined in the function inet_ntoa (). Instant
Take the result of the last call inet_ntoa () function to each time you call inet_ntoa ().
such as:
Char * a1, A2;
A1 = INET_NTOA (INA1.SIN_ADDR); / * this is 166.111.69.52 * /
A2 = INET_NTOA (INA2.SIN_ADDR); / * this is 166.111.69.53 * /
Printf ("Address 1:% S / N", A1);
Printf ("Address 2:% S / N", A2);
Will be displayed:
Address 1: 166.11.69.53
Address 2: 166.111.69.53
Chapter 6 Berkeley Socket - 147 -
If you want to save the results, then you can save the result to another at each call inet_ntoa ().
A string in your own string.
Behind it will be described how to convert the domain name to IP.
6.6 Basic socket call
Linux supports Berkeley (BSD) style socket programming. It also supports connection and non-connection types
Socket.
Server and clients are to create a connection before switching data. No connection
The data is exchanged as part of the information. No matter that way, the server always starts, tied yourself
Banding on a socket and listen to information. How do you try to listen to you?
The type of connection set is set.
Some system calls you need to know:
l stegket ()
l bind ()
l connectionct ()
l listen ()
l accept ()
l send ()
l Recv ()
l sendto ()
l Recvfrom ()
l close ()
l shutdown ()
l setsockopt ()
l getsockopt ()
l getPeername ()
l getsockname ()
l gethostbyname ()
l gethostbyaddr ()
l getProtobyname ()
l fcntl ()
We will introduce these system calls in detail below.
6.6.1 Socket () function
Take the socket descriptor! (Remember that we have said before? It is actually a file descriptor)
The definition of the Socket function is the following:
#include
#include
INT Socket (int Domain, int type, int protocol);
- 148 - Linux network programming
Do you have some doubts about Int Domain and Int Type, int protocol? What is the parameter called socket ()
?
First, Domain needs to be set to "AF_INET", just like Struct SockAddr_in above. Then, Type
The parameter tells the kernel This socket is what type, "sock_stream" or "SOCK_DGRAM". At last,
Just set Protocol to 0.
Note: In fact, the Domain parameter can take many values outside "AF_INET", and the Types parameter can also take the "SOCK_STREAM" or "SOCK_DGRAM". Specifically you can refer to the Socket's Man Pages (Help page).
There is no name when the socket is created. Client of client reads it with the name of the socket. This is the following binding function
What to do.
The socket () function is just a simple return of the socket descriptor you can use later. If an error occurs,
The socket () function returns -1. The global variable errno will be set to the error code. (Can refer to Perror () Man
Pages)
6.6.2 bind () function
The bind () function can help you specify a port used by a socket.
When you use the socket () function to get a socket descriptor, you may need to bind the socket to one of you.
Port on the machine.
l When you need a port listening listen () action, wait for accepting a request, usually
After this step. For example, network mud, telnet a.b.c.d 4000.
l If you just want to connect a server, it is when connecting the connect () operation.
It is not necessary.
The system call declaration of bind () is as follows:
#include
#include
INT Bind (int Sockfd, struct sockaddr * my_addr, int addrlen);
Parameter Description:
l SOCKFD is a socket descriptor returned by the socket () function.
l my_addr is a pointer to the Struct SockAddr that contains information about your address: name,
Port and IP addresses.
l Addrlen can be set to SIZEOF (Struct SockAddr).
Ok, let's see a program:
#include
#include
#include
#define myport 4000
Main ()
{Int SockFD;
Chapter 6 Berkeley Socket - 149 -
Struct SockAddr_in my_addr;
Sockfd = Socket (AF_INET, SOCK_STREAM, 0); / * In your own program * /
/ * To check! ! * /
MY_ADDR.SIN_FAMILY = AF_INET; / * Host byte order * /
MY_ADDR.SIN_PORT = HTONS (MyPort); / * Network byte order, short integer * /
MY_ADDR.SIN_ADDR.S_ADDR = INET_ADDR ("166.111.69.52");
Bzero (& (my_addr.sin_zero), 8); / * will remain in the entire structure * /
/ * Part of the data is set to 0 * /
/ * Don't forget to join the code to judge Bind error in your own program! ! * /
Bind (SockFD, Struct SockAddr *) & my_addr, sizeof (struct sockaddr);
??
??
There are some coded code segments here:
l my_addr.sin_port is a network byte order.
l my_addr.sin_addr.s_addr is also a network byte order.
l The header file included in the code segment, there may be a little difference in different systems. (But in Linux
This is this) If not this, you can check the Man Pages to get help.
Finally, bind () can automatically get your own IP address and port in the program.
code show as below:
MY_ADDR.SIN_PORT = 0; / * Randomly select a port * /
MY_ADDR.SIN_ADDR.S_ADDR = INADDR_ANY; / * Using your own address * /
As above, by setting my_addr.sin_port is 0, bind () can know you want it to help you choose the right port;
By setting my_addr.sin_addr.s_addr as INADDR_Add (bind () knows that you want it to fill S_ADDR as transport
The IP of the machine of this process. All this can require bind () to help you complete.
If you pay attention to some details, you may find that I have not converted INADDR_ANY to the network.
Byte order! This, the value of INADDR_ANY is 0, 0 is 0, no matter what order, the order of ordering,
It is constant.
Some readers will think, because I use INADDR_any is a #define, then put my program transplant
To another system, if INADDR_any there is such a definition: #define inaddr_any 100,
So, is my program not running? Then the code below is OK.
MY_ADDR.SIN_PORT = HTONS (0); / * Randomly select an unused port * /
MY_ADDR.SIN_ADDR.S_ADDR = HTONL (INADDR_ANY); / * Using your own IP address * /
Now that we are already so rigorous, no time for any value of INADDR_any calls bind
Will have trouble.
When the bind () function calls an error, it also returns -1 as a flag that is incorrect. Errn's value is wrong
Code.
Another thing to point out is: When you call bind (), don't set the port number! small
All ports of 1024 are all retained as the system using port, without root rights cannot be used. You can
Use any ports of more than 1024, until 65535: The largest port number you may use (of course, you still
- 150 - Linux network programming
To ensure that the port you want to use is not used by other programs).
Finally, pay attention to bind () is: Sometimes you don't have to call bind () to create a network connection. For example, you only
I want to connect to a remote host to communicate, you don't care which port you use.
Communication (such as Telnet), then you can simply call the connect () function, connect () will automatically find
Out of a unused port on the local machine, then call Bind () to bind its socket to that port.
6.6.3 Connect () function
Let us spend a little time to assume that you are a Telnet application. Your user commands you create a set
Word descriptor. You follow the command and call socket (). Then, the user tells you to connect to "166.111.69.52"
23 port (standard Telnet port) ?? What should you do?
You are fortunate: Telnet Apps, you are now reading is the socket of the network connection section:
CNECT ().
The definition of the Connect () function is like this: #include
#include
INT Connect (int sockfd, struct sockaddr * serv_addr, int addrlen);
The three parameters of Connect () are as follows:
l SockFD: Sackage file descriptor, returned by the socket () function.
l Serv_addr is a structure in which IP addresses and port information stored remote computers.
l Addrlen should be SizeOf (Struct SockAddr).
Let's take a look at the following program fragment:
#include
#include
#include
#define dest_ip "166.111.69.52"
#define dest_port 23
Main ()
{
Int sockfd;
/ * Will be used to store remote information * /
Struct SockAddr_in dest_addr;
/ * Note that in your own procedure is checked! ! * /
Sockfd = Socket (AF_INET, SOCK_STREAM, 0);
/ * Host byte order * /
dest_addr.sin_family = af_INet;
/ * Network byte order, short integer * /
DEST_ADDR.SIN_PORT = HTONS (dest_port);
Chapter 6 Berkeley Socket - 151 -
DEST_ADDR.SIN_ADDR.S_ADDR = INET_ADDR (DEST_IP);
/ * Set the space in the remaining structure 0 * /
Bzero (& (dest_addr.sin_zero), 8);
/ * Don't forget to check Connect () in your code! ! * /
Connect (Sockfd, Struct Sockaddr *) & Dest_addr, SizeOf (Struct SockAddr);
??
??
Returning again, be sure to detect the return value of Connect (): If an error occurs (eg, it is not possible to connect to the remote master
Machine, or the specified port of the remote host cannot be connected.) It will return the error value -1. Global variable errno
Error code will be stored.
Also, pay attention to we have not called the bind () function. Basically, we don't care about what port we use.
Communication, is it? What port we care is to connect to which of the hosts. Linux kernel is automatically for us
A local port that is not used is selected.
In the program for the connection-oriented protocol, the server performs the following function:
l Call the socket () function Create a socket.
l Call the BIND () function to bind yourself on an address.
l Call the listen () function Listen.
l Call the accept () function to accept all the introduced requests.
l Call the RECV () function to get the introduced information and then call the send () answer.
6.6.4 Listen () function
The Listen () function is a function of waiting for someone else to connect and perform system listening requests. When someone is connected to you, you have
Two steps need to do: Wait for the connection request by listen () function, then use the accept () function to process. (ACCEPT () function
Introduced below).
Listen () function call is very simple. The function declaration is as follows:
#include
INT Listen (int suckfd, int backlog); the parameters of the Listen () function are as follows:
l SockFD is a socket descriptor that is obtained by a socket () system call.
l Backlog is the maximum number of unprocessed connection request queues that can be accommodated.
What does backlog do something mean? Each new request must enter a new request queue, wait
Listen's program call accept () (ACCEPT () function is described below) The function is to accept this connection. When the system has not
When you call the accept () function, if there are a lot of connections, the maximum number of locations can wait is backlog.
Numerical value. You can set it into a value (recommended) between 5 and 10.
Like all functions above, Listen () If returns -1, then explain the execution of listen () ().
Error. Error code is stored in Errno in Errno.
Then we need to specify local ports because we are waiting for others to connect. So, in the Listen () function
Before using it, we need to use a bind () function to specify which port value is used locally.
- 152 - Linux network programming
If you want to accept a foreign connection request on a port, the order in which the function is:
Socket ();
Bind ();
Listen ();
/ * Call the accept () function here * /
??
The routine will not be given below because listen () is very easy to understand. Case in the ACCEPT () function description
There are listen () use.
6.6.5 ACCEPT () function
Functions accept () have some difficulties. When calling it, the rough process is the following:
l Someone tries to call Connect () from a far away place to connect to a port on your machine (of course
You are already listen ()).
l His connection will be called by Listen to wait for the call to wait for the accept () function (joining the most waiting queue)
The number is determined by the second parameter backlog called the listen () function).
l You call the accept () function telling him that you are ready to connect.
l account () functions will return to a new socket descriptor back, and this descriptor represents this connection!
Ok, at this time, you have two socket descriptors, and the one returned to you is the connection to the remote computer, and
The first socket descriptor is still listen () on the original port on your machine.
At this time, the new socket descriptor you got will be able to perform Send () operations and RECV ().
Below is the declaration of the accept () function:
#include
INT Accept (int SockFD, Void * Addr, INT * AddRlen);
The parameters of the accept () function are as follows:
l SockFD is a socket descriptor in listen ().
l Addr is generally a pointer to the struct sockaddr_in structure; there is a remote connection
Computer information (such as IP addresses and ports of remote computers).
l Addrlen is a local integer value, which is transmitted to Accept () before its address. It should be
SIZEOF (STRUCT SOCKADDR_IN); Accept () does not store data in the Addr in Addr. in case
The amount of data stored in the ADDR is not addrlen, and the accept () function changes the value of addrlen to reverse.
At this case.
The reader should now think that if the accept () failed, the accept () function returns -1 to indicate that the call failed, and the global variable errno will store the error code.
Let's take a segment of the program:
#include
#include
#include
/ * Port number * /
Chapter 6 Berkeley Socket - 153 -
#define myport 4000
/ * Wait for the queue to store how many unable access () processes * /
#define backlog 10
Main ()
{
/ * Used to listen to the socket socket SOCK_FD of the network connection, the user is connected to the socket uses new_fd * /
Int sockfd, new_fd;
/ * Local address information * /
Struct SockAddr_in my_addr;
/ * Connector's address information * /
Struct SockAddr_in their_addr;
INT SIN_SIZE;
/ * Remember this part of this part to check! * /
Sockfd = Socket (AF_INET, SOCK_STREAM, 0);
/ * Host byte order * /
MY_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
MY_ADDR.SIN_PORT = HTONS (MyPort);
/ * Automatic assignment for your own IP * /
MY_ADDR.SIN_ADDR.S_ADDR = INADDR_ANY
/ * Clear all the unused parts in the structure * /
Bzero (& (My_ADDR.SIN_ZERO, 8);
/ * Don't forget to call the program call in your own program needs to be detected! ! * /
Bind (SockFD, Struct SockAddr *) & my_addr, sizeof (struct sockaddr);
Listen (Sockfd, Backlog);
SIN_SIZE = SIZEOF (struct sockaddr_in);
New_fd = accept (sockfd, & their_addr, & sin_size);
??
??
Note: We use the socket descriptor new_fd to make all Send () and RECV () calls. If you
Just want to get a separate connection, then you can turn off the original SOCK_FD (call close ()), this
It can block the later connection.
In the connection-oriented communication, the client should do some things:
- 154 - Linux network programming
l Call the socket () function Create a socket.
l Call the connect () function attempts to connect the service.
l If the connection successfully calls the Write () function request data, call the read () function to receive the incoming response.
6.6.6 Send (), RECV () function
These two functions are the most basic, and the function of communication is performed by the connection of the socket stream.
If you want to use the connectionless user datagram, refer to the SENDTO () and RECVFROM () functions.
Declaration of Send () function:
#include
#include
Int Send (int Sockfd, Const Void * MSG, INT LEN, INT FLAGS);
The parameters of Send are as follows:
l SockFD is a socket descriptor that represents your connection with the remote program.
l MSG is a pointer to point to the address of the information you want to send.
l let is the length you want to send information.
l Flags Send tag. It is generally set to 0 (you can view Send's Man Pages to get other parameter values and understand the meaning representing each parameter).
Let's take a look at the code snippet about the send () function:
Char * msg = "Hello! World!";
INT LEN, BYTES_SENT;
??
??
LEN = Strlen (MSG);
BYTES_SENT = Send (sockfd, msg, len, 0);
??
??
??
The send () function returns the length of it truly sending data after the call.
Note: The data sent by Send () may be less than the length you give to the parameters!
Since the length of the data contained in the parameter you contain is much greater than the data you can send at Send (), the send () function
Just send the maximum data length it can send, then it believes that you will call the remaining data again to perform the second time.
So, remember that if the return value of the send () function is less than LEN, you need to send the remaining data again. Fortunately, if
The bag is small enough (less than 1K), and send () generally transmits light at a time.
Like the above function, if an error occurs, return -1, error code storage in global changes
Errno.
Let's take a look at the RECV () function.
Function RECV () calls are very similar to send () in many ways, the following is a declaration of the RECV () function:
#include
#include
Chapter 6 Berkeley Socket - 155 -
Int Recv (int Sockfd, Void * Buf, int LEN, UNSIGNED INT FLAGS);
The parameters of the RECV () are as follows:
l SockFD is a socket descriptor you want to read data.
l Buf is a pointer, pointing to the memory cache area that you can store data.
l Lin is the maximum size of the cache area.
l Flags is a logo of the RECV () function, usually 0 (please refer to RECV () for specific values and meanings.
MAN Pages).
RECV () returns the length of the data it really received. (The length of data in BUF) is stored). If returned
-1 represents an error (such as interruption outside the network, the other party closed the socket connection, etc.), the global variable errno
Face stores the error code.
Very simple, isn't it? Now you can use a socket connection to send data and accept data!
Ya! You have now become a web programmer under Linux!
6.6.7 Sendto () and Recvfrom () functions
These two functions are used when there is no connected UDP communication. Using these two functions, the data will not
Established on the network transmitted on any connection. Because the data settlement is unable to connect the remote host, think about us
What do you need to know before sending data?
correct! Is the IP address and port of the remote host!
The following is a declaration of sendto () functions and RECVFROM () functions:
#include
#include
Int Sendto (int Sockfd, Const void * MSG, Int Len, unsigned int flags,
Const struct sockaddr * to, int toolen;
As you can see, this function is basically consistent with the Send () function.
l SockFD is a socket descriptor that represents your connection with the remote program.
l MSG is a pointer to point to the address of the information you want to send.
l let is the length you want to send information.
l Flags Send tag. It is generally set to 0. (You can view Send's Man Pages to get other participants
Values and understand the meaning representing each parameter)
l TO is a pointer to the struct sockaddr structure, which contains IP addresses and ports of remote hosts.
data.
l Tolen just pointed out the size of Struct SockAddr in memory.
Like Send (), sendto () returns the number of bytes it really sends (of course, it is also true, it is true.
The number of bytes sent may be less than the number of bytes you give it). When it is wrong, it is also -1,
At the same time, the global variable errno stores the error code.
Similarly, the RECV () function and the RECVFROM () function are basically consistent.
The declaration of Recvfrom () is:
#include
- 156 - Linux network programming
#include
Int Recvfrom (int sockfd, void * buf, int LEN, unsigned int flags
Struct SockAddr * from, int * fromlen);
Its parameters are as follows:
l SockFD is a socket descriptor you want to read data.
l Buf is a pointer, pointing to the memory cache area that you can store data.
l Lin is the maximum size of the cache area.
l Flags is a logo of the RECV () function, usually 0 (please refer to RECV () for specific values and meanings.
MAN Pages).
l from a local pointer, pointing to a struct sockaddr structure (there is a source IP address and end
The number of ports).
l fromlen is a pointer to an INT data, and its size should be Sizeof (Struct
SockAddr). When the function returns, the data pointing to the Formlen is the actual situation of Struct SockAddr, pointing to Form.
size.
Recvfrom () returns the number of bytes it receives, if an error occurs, it returns -1, global variable errno
The error code is stored.
If a message is bigger buffer, the additional information will be cut off. This call can be returned immediately, too
Can wait for a long time. This depends on what type you set to Flags. You can even set up a timeout value.
More information of RecVFrom can be found in Man Pages.
Note: If you use cnnect () to connect to a server program of a data settlement, then you can
To use the Send () and RECV () functions to transfer your data. Don't think you are using a streaming socket, you
It is still a socket that is still a user datagram, but the socket interface is in Send () and RECV ()
Help you add the information of the target address, the target port.
6.6.8 Close () and shutdown () functions
After the program is transmitted, you need to close the connection represented by this socket descriptor. Realize this
Often simply, just use standards of closing files: close ().
Instructions:
Close (SockFD);
After performing Close (), the socket will not be read and write. Any operation of reading and writing to a socket descriptor will receive an error.
If you want to make further operations for closing the network socket, you can use the function shutdown ().
It allows you to perform one-way shutdown operation, or all disabled.
Shutdown () statement is:
#include
INT Shutdown (int Sockfd, int ~);
Its parameters are as follows:
l Sockfd is a socket descriptor you want to close.
l HOW can take the following value. 0 indicates that the reception operation of the subsequent data is not allowed; 1 means that the data is not allowed
Chapter 6 Berkeley Socket - 157 -
Transmitting operation; 2 indicates that any operation (including reception, sending data) is not allowed, as in Close ()
Shutdown () If the execution will return 0, if an error occurs during the call, it will return -1, all
The error code is stored in Errno in Errno.
If you use the shutdown () function on a unconnected data settlement (I still remember the data settlement)
Does the terminal UDP for Connect () operation? ), It will not do anything.
6.6.9 setsockopt () and getsockopt () functions
The Socket library provided by Linux contains an error (bug). This error is expressible to you can't be a socket.
Newly enabled the same port number, even after you are properly closed. For example, for example, you write a service
The program waited on a socket. The server opens the socket and listens on it is no problem. anyway,
There are always some reasons (whether it is normal or abnormal end procedures) makes your program need to restart. But restart
You can't bind it on that port after moving. Error code returned from bind () system is always reported
Say that the port you try to connect has been bound by other processes.
The problem is that the Linux kernel never marks the port after the end of a binding socket. Mostly
In the LINUX / UNIX system, the port can be reused by a process, or even other processes.
The way to wind open this problem in Linux is that when the socket has been opened but not used
Setsockopt () system calls to set options (Options). Setsockopt () call setting options and getsockopt ()
Options from a given socket.
Here is the syntax of these calls:
#include
#include
INT GetSockopt (int sockfd, int discount, int name, char * value, int * optlen);
Int setsockopt (int sockfd, int discount, int name, char * value, int * optlen);
Below is the parameter description of two calls:
l SockFD must be an open socket.
l Level is a Protocol Level (TCP / IP Protocol) (IPPROTO_TCP,
Set of SLR standards utility sol_socket).
l Name Options There is a detailed description in the socket manual (Man Page).
l Value points to the value of the value gaged for the getSockopt () function, the address set by the setSockOpt () function. l Optlen pointer points to an integer, which contains the length of the parameter to byte.
Now let's go back to Linux 's mistakes. When you open a socket, you must use the following code segment.
To call the setsockopt () function:
/ * Setting parameter value * /
OPT = 1; len = sizeof (opt);
/ * Set the socket properties * /
Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);
Setsockopt () functions There are still many other usages, please refer to the Help page (MAN PAGES).
6.6.10 getPeername () function
This function can get remote information of a socket already connected (such as IP address and port), tell
- 158 - Linux network programming
Who is you in remote and you connect?
Its statement is:
#include
INT getPeername (int SockFD, Struct SockAddr * Addr, INT * AddRlen);
Here is the parameter description:
l SockFD is the socket descriptor you want to get remote information.
l AddR is a pointer to Struct SockAddr (or Struct SockAddr_in).
l Addrlen is a pointer to the int, which should be assigned to the size of the SIZEOF (STRUCT SOCKADDR).
If an error occurs during the execution of the function, the function will return -1, and the error code is stored in the global variable.
Errno.
When you have an IP address of the remote connection user, you can use inet_ntoa () or gethostbyaddr ().
Out of information or further processing.
6.6.11 gethostname () function
The gethostname () function can obtain information about the local host. It is easy to use than getPeername ().
It returns the name of the computer being executing it. The name returned can be used by the gethostbyname () function.
This allows the IP address of the local host.
Here is its statement:
#include
INT gethostname (char * hostname, size_t size);
The parameters are as follows:
l Hostname is a pointer to the character array. When the function returns, the data in it is this
The name of the host's host.
l size is the length of the array pointing to HostName.
Function If successfully executed, it returns 0, if an error occurs, return -1, the global variable errno is wrong
Misuse.
6.7 DNS operation
6.7.1 Understanding DNS
Should you know DNS? DNS is an abbreviation for "Domain Name Service". With it,
You can get the IP address represented by this name through a very strong Internet name. Convert to IP
After the address, you can use the standard socket function (bind (), connect (), sendto (), or anything else
The function to use).
Here, if you enter a command:
$ telnet bbs.tsinghua.edu.cn
Telnet can know that it needs to be connected to 202.112.58.200. This is achieved by DNS. 6.7.2 and DNS related functions and structures
How does DNS work? You can use the gethostbyName () function.
Chapter 6 Berkeley Socket - 159 -
Its declaration is as follows:
#include
Struct Hostent * gethostByName (const char * name);
As you can see, it returns a pointer to the struct hostent. Struct hostent is defined in this way
of:
Struct hostent {
Char * h_name;
Char ** h_aliases;
INT H_ADDRTYPE;
Int h_gength;
Char ** h_addr_list;
}
#define h_addr h_addr_list [0]
Below is an explanation of representative meaning of the above domain:
l h_name is a formal name of this host.
l h_aliases is an array ending with NULL (empty characters), which stores the host's alternate name.
l h_addrtype is the type of return address, which is generally "AF_INET".
l h_length is the byte length of the address.
L h_addr_list is an array ends with 0, stores the network address of the host.
Note: The network address is stored in the network byte order.
L h_addr - The first member of the H_Addr_List array.
GethostByname () Returned to the structure Struct Hostent, if an error occurs, it will return NULL
(But Errno does not represent the error code, the tips in H_ERRNO stores the incorrect error code. Refer to the following HERROR () function).
How should I use this function? It looks a little scary. Believe me, it is far more than it.
It looks easy.
6.7.3 DNS routine
Let's take a look at a routine:
#include
#include
#include
#include
#include
#include
int
Main (int Argc, char * argv [])
{
Struct hostent * h;
/ * Detect whether the parameter in the command line exists * /
- 160 - Linux network programming
IF (argc! = 2)
/ * If there is no parameters, give the usage method * /
FPRINTF (stderr "usage: getip address / n");
/ * Then exit * /
Exit (1);
}
/ * Acquired host information * /
IF ((h = gethostbyname) == NULL)
{
/ * If gethostbyname fails, an error message is given * /
Herror ("gethostbyname");
/ * Then exit * /
Exit (1);
}
/ * Information obtained by the print program * /
Printf ("Host Name:% S / N", H-> h_name);
Printf ("IP Address:% S / N", INET_NTOA (* (Struct In_ADDR *) H-> h_addr));
/ * Return * /
Return 0;
}
Using the gethostbyName () function, you cannot use PERROR () to output an error message (because the error code is stored in h_errno instead of errno. So, you need to call the Herror () function.
Is it very magical? You are simply transmitted to getHostbyName () a machine name
("Bbs.tsinghua.edu.cn"), then obtain other information such as IP from the returned structure struct hostent.
The program of the output IP address in the program needs to explain:
H-> h_addr is a char *, but the inet_ntoa () function needs to pass a Struct in_addr structure.
Therefore, the H-> h_addr is forced to struct in_addr *, and then all data is obtained.
6.8 Sociographs of Client / Server Structure Implementation
It is now a server / client world. Almost all work on the network is from the client to the server
Send a request is implemented. For example, Telnet, when you send a connection request to a 23-port of a remote host,
The service program (Telnetd) on the remote host will accept this remote connection request. Allows you to do Login operations.
and many more.
Any way communication can be used between servers and clients, including SOCK_STREAM, SOCK_DGRAM,
Or any other way (as long as they use the same method).
Chapter 6 Berkeley Socket - 161 -
Some Server / Client's examples are telnet / telnetd, ftp / ftpd, bootp / bootpd. Use ftp every time you
You both use the FTPD service on the remote host. In general, there is a program waiting for a connection on the server. Attach
When you receive a connection, the server program calls the system function fork () to get a child process, dedicated to this
Connection operation.
Let's take a simple stream server:
6.8.1 Simple Flow Server
All the work of this server is to send a string to the remote terminal: "Hello, World!" What you need
What to do is to start this server on the command line, then use Telnet to connect to this unit on another machine.
On the server you wrote:
$ telnet remotehostname 4000
Remotehostname is the machine name of the server you run.
Server code:
#include
#include
#include
#include
#include
#include
#include
#include
/ * The local port * / server to listen to * /
#define myport 4000
/ * How much does it accept at the same time without Accept's connection * /
#define backlog 10
Main ()
{
/ * Listening on Sock_FD, new_fd accepts new connections * /
INT SOCK_FD, New_FD;
/ * Your address information * /
Struct SockAddr_in my_addr;
/ * Connector's address information * /
Struct SockAddr_in their_addr;
INT SIN_SIZE;
/ * Here is the error check we have always emphasized. Returns * / if ((sockfd = - 162 - Linux network programming) if you call socket () error
Socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
/ * Output error prompt and exit * /
PERROR ("socket");
Exit (1);
}
/ * Host byte order * /
MY_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
MY_ADDR.SIN_PORT = HTONS (MyPort);
/ * Pack the IP of the running program machine into S_ADDR * /
MY_ADDR.SIN_ADDR.S_ADDR = INADDR_ANY
/ * Clear the remaining space of this structure * /
Bzero (& (My_ADDR.SIN_ZERO, 8);
/ * Here is the wrong check we have always emphasized! ! * / if (Bind (SockFD, (Struct SockAddr *) & my_addr,
SIZEOF (STRUCT SOCKADDR) == -1)
{
/ * If you call bind () fail, give an error message, exit * /
PERROR ("bind");
Exit (1);
}
/ * Here is the wrong check we have always emphasized! ! * /
IF (Listen (Sockfd, Backlog) == -1)
{
/ * If you call Listen fail, give an error prompt, exit * /
PERROR ("listen");
Exit (1);
}
While (1)
{
/ * Here is the primary accept () loop * /
SIN_SIZE = SIZEOF (struct sockaddr_in);
/ * Here is the wrong check we have always emphasized! ! * /
Chapter 6 Berkeley Socket - 163 -
IF ((new_fd = accept (sockfd, (struct socaddr *) & their_addr, & sin_size)) == -1)
{
/ * If an error occurs when you call accept (), an error message is given to enter the next loop * /
PERROR ("accept");
CONTINUE;
}
/ * The server gives the information that appears * /
Printf ("Server: Got Connection FROM% S / N", INET_NTOA (THEIR_ADDR.SIN_ADDR);
/ * Here will create a child process to communicate with the socket that has just been established. * /
IF (! fork ())
/ * Here is a child process * /
/ * Here is the error check! * /
IF (send (new_fd, "hello, world! / n", 14, 0) == -1)
{
/ * If it is wrong, give an error prompt, then close this new connection, exit * /
PERROR ("Send");
Close (new_fd);
exit (0);
}
/ * Close this socket connection represented by New_FD * /
Close (new_fd);
}
}
/ * Waiting for all child processes to exit * /
While (Waitpid (-1, null, wnohang> 0);
}
In order to more clearly describe the running process of this socket server, I write all the code in this big.
The main () master function. If you think it is divided into several subroutines, you will clear some, you can put this procedure.
Change into a few small functions.
You can use the next socket client to get "Hello, World!" String. 6.8.2 Simple Flow Socket Client Program
This program is simpler than the server-side program. The work it does is Connect () to the server 4000
The port is displayed, and then the string sent by the server is displayed.
Client program:
#include
#include
#include
#include
#include
- 164 - Linux network programming
#include
#include
#include
/ * The port number of the server program listener * /
#define port 4000
/ * We can receive the maximum number of bytes available once * /
#define maxDataSize 100
int
Main (int Argc, char * argv [])
{
/ * Socket descriptor * /
Int Sockfd, Numbytes;
Char buf [maxdatasize];
Struct hostent * he;
/ * Host information of the connector * /
Struct SockAddr_in their_addr;
/ * Check parameter information * /
IF (argc! = 2)
{
/ * If there is no parameters, it will give it to the usage method * /
FPRINTF (stderr, "usage: client hostname / n");
Exit (1);
}
/ * Acquired host information * /
IF ((he = gethostByname) == null)
/ * If a getHostByname () has an error, the error message is displayed and exits * /
Herror ("gethostbyname");
Exit (1);
}
IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) == -1) {
/ * If there is an error in Socket () call, the error message is displayed and exits * /
PERROR ("socket");
Exit (1);
}
Chapter 6 Berkeley Socket - 165 -
/ * Host byte order * /
THEIR_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
THEIR_ADDR.SIN_PORT = HTONS (port);
THEIR_ADDR.SIN_ADDR = * (Struct In_Addr *) He-> h_addr);
/ * Clear part left in the structure * /
Bzero (& (THEIR_ADDR.SIN_ZERO, 8);
IF (Connect (Sockfd, Struct SockAddr *) & their_addr, sizeof (struct sockaddr)) == -1)
{
/ * If connection error is established, an error message is displayed, exit * /
PERROR ("Connect");
Exit (1);
}
IF ((NumBytes = Recv (SockFD, BUF, MaxDataSize, 0)) == -1)
{
/ * If the data is received, the error message is displayed and exits * /
PERROR ("RECV");
Exit (1);
}
BUF [NumBytes] = '/ 0';
Printf ("Received:% S", BUF);
Close (SockFD);
Return 0;}
Note: Obviously, you must start Server before running the Client. Otherwise, the execution of the Client will be wrong (display "Connection
Refused ").
6.8.3 Data Supplies Slim Scribble Routines (DataGramsockets)
Here I don't have too much description of the datagram. You will see another pair of routines (using datagrams): Talker.c
And listener.c.
Listener runs on a machine as a server program, which listens the port 5000.
Talker sends a UDP packet to the 5000 port of the server, transmitting the user's data.
Here is the source code of Listener.c:
#include
- 166 - Linux network programming
#include
#include
#include
#include
#include
#include
#include
/ * The port number to connect * /
#define myport 5000
/ * The longest data that can be received * /
#define maxbufflen 100
Main ()
{
Int sockfd;
/ * Native address information * /
Struct SockAddr_in my_addr;
/ * Connect this address information * /
Struct SockAddr_in their_addr;
Int Addr_len, Numbytes;
Char buf [maxbuflen];
/ * Get a socket descriptor * /
IF ((SockFD = Socket (AF_INET, SOCK_DGRAM, 0) == -1)
{
/ * If the socket descriptor fails, an error message is given, exit * /
PERROR ("socket");
Exit (1);
}
/ * Host byte order * /
MY_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
MY_ADDR.SIN_PORT = HTONS (MyPort);
/ * Automatically set it to your own IP * /
MY_ADDR.SIN_ADDR.S_ADDR = INADDR_ANY
Chapter 6 Berkeley Socket - 167 -
/ * Clear the remaining space of the structure * /
Bzero (& (My_ADDR.SIN_ZERO, 8);
/ * Bind port * /
IF (bind (STRUCKFD, Struct SockAddr *) & my_addr, sizeof (struct sockaddr) == -1)
{
/ * If the binding port is wrong, the error message is displayed and then exits * /
PERROR ("bind");
Exit (1);
}
Addr_len = SizeOf (struct sockaddr);
/* Receive data*/
IF ((NumBytes = Recvfrom (Sockfd, Buf, Maxbufflen, 0,
(STRUCT SOCKADDR *) & THEIR_ADDR, & Addr_len)) == -1)
{
/ * If the recvfrom () calls an error, then exit after the error message is displayed * /
PERROR ("Recvfrom");
Exit (1);
}
/ * Display received data * /
Printf ("Got Packet FROM% S / N", INET_NTOA (THEIR_ADDR.SIN_ADDR); Printf ("Packet IS% D Bytes Long / N", NumBytes);
BUF [NumBytes] = '/ 0';
Printf ("Packet Contains /"% S / "/ N", BUF);
/ * Close the socket connection * /
Close (SockFD);
}
Note that when we call the socket () function, it is used as a sock_dgram as a parameter. And, we don't
Listen () or accept () is required. This is because we used the connectionless user data sets!
The following is the source code of Talker.c:
#include
#include
#include
#include
#include
#include
- 168 - Linux network programming
#include
#include
#include
/ * Port to connect * /
#define myport 5000
Int main (int Argc, char * argv [])
{
Int sockfd;
/ * Connector's address information * /
Struct SockAddr_in their_addr;
Struct hostent * he;
INT Numbytes;
IF (argc! = 3)
{
/ * Check if there is a parameter, if not, then exit after using the method * /
FPRINTF (stderr, "usage: talker hostname message / n");
Exit (1);
}
IF ((he = gethostByname) == null)
{
/ * Obtain information about the host, if the error message is displayed, then the error message is displayed * /
Herror ("gethostbyname");
Exit (1);
}
IF ((SockFD = Socket (AF_INET, SOCK_DGRAM, 0) == -1)
{
/ * Apply for a data report set descriptor, with failed, exit * /
PERROR ("socket");
Exit (1);
}
/ * Host byte order * /
THEIR_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
Chapter 6 Berkeley Socket - 169 -
THEIR_ADDR.SIN_PORT = HTONS (MyPort);
THEIR_ADDR.SIN_ADDR = * (Struct In_Addr *) He-> h_addr);
/ * Clear parts unused in the structure * /
Bzero (& (THEIR_ADDR.SIN_ZERO, 8);
IF ((NumBytes = Sendto (Sockfd, Argv [2], Strlen (Argv [2]), 0,
(Struct SockAddr *) & their_addr, sizeof (struct sockaddr)) == -1)
{
/ * Send the information to the specified host specified port, if an error is prompted * /
PERROR ("Recvfrom");
Exit (1);
}
Printf ("SENT% D Bytes TO% S / N", NumBytes, INET_NTOA (THEIR_ADDR.SIN_ADDR);
/ * After closing the socket descriptor, exit * / close (sockfd);
Return 0;
}
The above two programs, you need to run Listener on a host, then run on another host
Talker. Did you see the communications between them now?
Finally, we should pay attention to a point: use the connected data settlement set. Because we are talking about the datagram, so
We need to know it. If our Talker program uses the connect () function to connect the address of the listener, then
The Talker program can use SENT () and RECV () to process data. Because the Talker program has been in the connect () function
I know the address and port number of the remote host.
6.9 Reserved Port
6.9.1 Introduction
Most web applications use two protocols: Transfer Control Protocol (TCP) and User Packet Protocol (UDP).
They all use a port number to identify the app. The port number is used by the program running on the host, so that
Tracked each application with the name of the name. How many applications are easier for the port number to make the operating system easier
The program is using the system and which services are valid.
In theory, port numbers can be assigned by administrators on each host. But in order to better communications, one is usually used.
Some agreements. These protocols enable the class that identifies a system to another system through the port number.
type. Based on this reason, most systems maintain a file that contains port numbers and what services they provide.
The port number is assigned from 1. The portion of usually the port number is exceeded by 255 is retained by the local host as private use. 1
The number between 255 is used for the processes and network services requested by the remote application. Each network communication cycle
The TCP application layer of the main computer is out. It is uniquely identified by two connected numbers. These two numbers set up
Tag. The two numbers that make up the socket are the IP address of the machine and the port number used by the TCP software.
Because network communication includes at least two machines, there is a socket on the machine sent and received. by
The IP address of each machine is unique. The port number is also unique in each machine, so the socket should be in the network.
- 170 - Linux network programming
This is unique. Such settings enables two applications in the network to interpire each other based on sockets.
Sending and receiving machines maintain a port table, which lists all activated port numbers. Both machines include one
The process is called binding, which is the entrance to each task, but it is exactly the opposite of the two machines. In other words, if one
The source port number of the machine is 23 and the destination port number is set to 25, then the source port number of the other machine is set to 25.
The destination port number is set to 23.
6.9.2 Reserved Port
The system has 1024 reserved ports. These ports are used in the system, in the system, only ROOT
Talent of rights can use ports below 1024 (including 1024)
Here is Redhat 6.0 / etc / service file:
[root @ bbs / etc] # Cat / etc / services
# / etc / service:
# $ ID: SERVICES, V 1.4 1997/05/20 19:41:21 Tobias EXP $
#
# Network Services, Internet Style
#
# Note That It is presently the policy of iana to assign a single well-knower
# Port Number for Both TCP And Udp; Hence, MOST Entries Here Have Two Entries
# Even if The protocol doesn't support udp operations.
# Updated from RFC 1700, "Assigned Numbers" (October 1994). Not all ports # are incrry, only the more common ones.
TCPMUX 1 / TCP # TCP Port Service Multiplexer
Ztelnet 2 / TCP
ECHO 7 / TCP
ECHO 7 / UDP
Discard 9 / TCP Sink Null
Discard 9 / UDP Sink Null
SYSTAT 11 / TCP USERS
Daytime 13 / TCP
Daytime 13 / UDP
NetStat 15 / TCP
QOTD 17 / TCP quote
MSP 18 / TCP # Message Send Protocol
MSP 18 / UDP # Message Send Protocol
Chargen 19 / TCP TTYTST SOURCE
Chargen 19 / UDP TTYTST SOURCE
FTP-DATA 20 / TCP
FTP 21 / TCP
Chapter 6 Berkeley Socket - 171 -
FSP 21 / UDP FSPD
SSH 22 / TCP # SSH Remote login protocol
SSH 22 / udp # ssh Remote Login Protocol
Telnet 23 / TCP
#STELNET 30 / TCP
# 24 - Private
SMTP 25 / TCP Mail
# 26 - Unassigned
Time 37 / TCP TIMSERVER
Time 37 / UDP TIMSERVER
RLP 39 / UDP Resource # Resource location
Nameserver 42 / TCP Name # Ien 116
Whois 43 / TCP NICNAME
RE-mail-ck 50 / tcp # Remote Mail Checking Protocol
RE-mail-ck 50 / udp # Remote Mail Checking Protocol
Domain 53 / TCP Nameserver # Name-Domain Server
Domain 53 / UDP Nameserver
MTP 57 / TCP # deprecated
Bootps 67 / TCP # bootp server
Bootps 67 / UDP
Bootpc 68 / TCP # bootp client
Bootpc 68 / UDP
TFTP 69 / UDP
Gopher 70 / TCP # internet gopher
GOPHER 70 / UDP
RJE 77 / TCP NETRJS
Finger 79 / TCP
WWW 80 / TCP http # WorldwideWeb HTTP
WWW 80 / udp # Hypertext Transfer Protocol
Link 87 / TCP TTYLINK
Kerberos 88 / TCP Kerberos5 KRB5 # kerberos V5
Kerberos 88 / UDP Kerberos5 KRB5 # kerberos v5
SUPDUP 95 / TCP
# 100 - reserved
Hostnames 101 / TCP hostname # USUALLY from SRI-NIC
ISO-TSAP 102 / TCP TSAP # part of isode.
Csnet-NS 105 / TCP CSO-NS # also ready by CSO Name Server
CSNET-NS 105 / UDP CSO-NS
# unfortunately the poppassd (eudora) Uses a port Which Has Already
- 172 - Linux network programming
# Been Assigned to a Different Service. we list the poppassd as an an on # alias here. This service is service.
# (Due to a bug in inetd the 3com-tsmux line is disk)
# 3com-tsmux 106 / tcp poppassd
# 3com-TSMUX 106 / UDP Poppassd
RTELNET 107 / TCP # Remote Telnet
RTELNET 107 / UDP
POP-2 109 / TCP PostOffice # POP VERSION 2
POP-2 109 / UDP
POP-3 110 / TCP # POP VERSION 3
POP-3 110 / UDP
SunRPC 111 / TCP Portmapper # RPC 4.0 Portmapper TCP
SunRPC 111 / UDP Portmapper # RPC 4.0 Portmapper UDP
#BY Zixia RPC 111 / TCP Portmapper # RPC 4.0 Portmapper TCP
#RPC 111 / UDP Portmapper # RPC 4.0 Portmapper UDP
Auth 113 / TCP Authentication TAP Ident
SFTP 115 / TCP
UUCP-PATH 117 / TCP
NNTP 119 / TCP READNEWS UNTP # USENET NEWS TRANSFER Protocol
NTP 123 / TCP
NTP 123 / UDP # Network Time Protocol
NetBIOS-NS 137 / TCP # NetBIOS Name Service
NetBIOS-NS 137 / UDP
NetBIOS-DGM 138 / TCP # NetBIOS DataGram Service
NetBIOS-DGM 138 / UDP
NetBIOS-SSN 139 / TCP # Netbios Session Service
NetBIOS-SSN 139 / UDP
IMAP2 143 / TCP IMAP # Interim Mail Access Proto V2
IMAP2 143 / UDP IMAP
SNMP 161 / UDP # Simple Net Mgmt Proto
SNMP-TRAP 162 / UDP SNMPTRAP # Traps for SNMP
CMIP-Man 163 / TCP # ISO MGMT over ip (cmot)
CMIP-MAN 163 / UDP
CMIP-Agent 164 / TCP
CMIP-Agent 164 / UDP
XDMCP 177 / TCP # x display mgr. Control Proto
XDMCP 177 / UDP
Nextstep 178 / tcp nextstep nextstep # nextstep window
Nextstep 178 / udp nextstep nextstep # server
BGP 179 / TCP # Border Gateway Proto.
Chapter 6 Berkeley Socket - 173 -
BGP 179 / UDP
ProSpero 191 / TCP # Cliff Neuman's Prospeo
Prospero 191 / UDP
IRC 194 / TCP # Internet relay chat
IRC 194 / UDP
SMUX 199 / TCP # SNMP UNIX Multiplexer
SMUX 199 / UDP
AT-RTMP 201 / TCP # AppleTalk Routing
AT-RTMP 201 / UDP
AT-NBP 202 / TCP # AppleTalk Name Binding
AT-NBP 202 / UDP
At-echo 204 / tcp # AppleTalk Echo
AT-ECHO 204 / UDP
AT-ZIS 206 / TCP # AppleTalk Zone Information
AT-ZIS 206 / UDP
QMTP 209 / TCP # The Quick Mail Transfer Protocol
QMTP 209 / UDP # The Quick Mail Transfer Protocol
Z3950 210 / TCP WAIS # NISO Z39.50 Database
Z3950 210 / UDP WAIS
IPX 213 / TCP # ipx
IPX 213 / UDP
IMAP3 220 / TCP # Interactive Mail Access
IMAP3 220 / UDP # Protocol v3
RPC2PortMap 369 / TCP
RPC2portmap 369 / UDP # CODA Portmapper
CODAAUTH2 370 / TCP
Codaauth2 370 / UDP # Coda Authentication Server
UListServ 372 / TCP # Unix ListServ
UListServ 372 / UDP
HTTPS 443 / TCP # mcom
HTTPS 443 / UDP # MCOM
SNPP 444 / TCP # Simple Network Paging Protocol
SNPP 444 / UDP # Simple Network Paging Protocol
SAFT 487 / TCP # Simple Asynchronous File Transfer
SAFT 487 / UDP # Simple Asynchronous File Transfer
NPMP-LOCAL 610 / TCP DQS313_QMASTER # npmp-local / DQS
NPMP-LOCAL 610 / UDP DQS313_QMASTER # npmp-local / DQS
NPMP-GUI 611 / TCP DQS313_EXECD # NPMP-GUI / DQS
NPMP-GUI 611 / UDP DQS313_EXECD # NPMP-GUI / DQS
HMMP-IND 612 / TCP DQS313_INTERCELL # HMMP Indication / DQS
- 174 - Linux network programming
HMMP-IND 612 / UDP DQS313_INTERCELL # HMMP Indication / DQS
#
# UNIX Specific Services
#
EXEC 512 / TCP
BIFF 512 / UDP COMSAT
Login 513 / TCP
WHO 513 / UDP Whod
Shell 514 / TCP CMD # no passwords ready
Syslog 514 / UDP
Printer 515 / TCP Spooler # line Printer Spooler
Talk 517 / UDP
NTALK 518 / UDP
Route 520 / UDP Router Routed # rip
TIMED 525 / UDP TIMESERVER
Tempo 526 / TCP NewDate
Courier 530 / TCP RPC
Conference 531 / TCP Chat
NetNews 532 / TCP Readnews
Netwall 533 / udp # -for Emergency Broadcasts
UUCP 540 / TCP UUCPD # uucp daemon
Afpovertcp 548 / TCP #Afp over TCP
Afpovertcp 548 / UDP # AFP over TCP
Remotefs 556 / TCP RFS_SERVER RFS # Brunhoff Remote FileSystem
Klogin 543 / TCP # kerberized 'rlogin' (V5) Kshell 544 / TCP Krcmd # kerberized 'r r (v5)
Kerberos-ADM 749 / TCP # kerberos 'Kadmin' (V5)
#
Webster 765 / TCP # Network Dictionary
Webster 765 / UDP
#
# From "assigned number":
#
#> The registered ports area not controlled by the Iana and on MOST SYSTEMS
#> can be used by Ordinary User Processes or Programs Executed by Ordinary
#> Users.
#
#> Ports are buying in TCP [45,106] to name the ends of logical
#> Connections Which Carry Long Term Conversations. for the purpose of
Chapter 6 Berkeley Socket - 175 -
#> Providing Services to Unknown Callers, a Service Contact Port IS
#> defined. This List specifies the port buy by the server process as it
#> Contact Port. While The Iana Can NOT Control Uses of these Ports IT
#> does register or list buys of these ports as a convience to the
#> Community.
#
Ingreslock 1524 / TCP
INGRESLOCK 1524 / UDP
Prospero-NP 1525 / TCP # Prospero Non-Privileged
ProSpeRo-NP 1525 / UDP
DataMetrics 1645 / TCP Old-Radius # DataMetrics / Old Radius Entry
DataMetrics 1645 / UDP Old-Radius # DataMetrics / Old Radius Entry
SA-MSG-Port 1646 / TCP Old-Radacct # SA-MSG-Port / Old Radacct Entry
SA-MSG-Port 1646 / UDP Old-Radacct # SA-MSG-Port / Old Radacct Entry
Radius 1812 / TCP # RADIUS
Radius 1812 / UDP # RADIUS
Radacct 1813 / TCP # Radius Accounting
Radacct 1813 / udp # Radius Accounting
CVSPSERVER 2401 / TCP # cvs client / server Operations
CVSPServer 2401 / UDP # cvs client / server operations
Venus 2430 / TCP # CODACON Port
Venus 2430 / UDP # venus callback / wbc interface
Venus-se 2431 / tcp # TCP Side Effects
Venus-se 2431 / udp # udp sftp side effect
Codasrv 2432 / TCP # not used
Codasrv 2432 / UDP # Server Port
Codasrv-se 2433 / tcp # TCP Side EffectscoDasRV-SE 2433 / UDP # UDP SFTP SIDE EFFECT
MySQL 3306 / TCP # mysql
MySQL 3306 / UDP # mysql
RFE 5002 / TCP # Radio Free Ethernet
RFE 5002 / UDP # actually uses udp only
CFENGINE 5308 / TCP # cfngne
Cfengine 5308 / udp # cfngne
BBS 7000 / TCP # BBS Service
# # # # # # #
# Kerberos (Project Athena / MIT) Services
# Note That Sests, Andre Unofficial. Sites Running
# v4 Should uncomment these and comment Out the v5 entries.
- 176 - Linux network programming
#
Kerberos4 750 / UDP Kerberos-IV KDC # kerberos (Server) UDP
Kerberos4 750 / TCP Kerberos-IV KDC # kerberos (Server) TCP
Kerberos_Master 751 / UDP # kerberos Authentication
Kerberos_master 751 / tcp # kerberos Authentication
Passwd_server 752 / udp # kerberos Passwd Server
KRB_PROP 754 / TCP # Kerberos Slave Propagation
Krbupdate 760 / TCP Kreg # kerberos Registration
Kpasswd 761 / TCP KPWD # kerberos "passwd"
KPOP 1109 / TCP # Pop with Kerberos
Knetd 2053 / TCP # kerberos de-multiplexor
ZEPHYR-SRV 2102 / UDP # zephyr server
ZEPHYR-CLT 2103 / UDP # zephyr serv-hm connection
Zephyr-HM 2104 / UDP # zephyr hostmanager
Eklogin 2105 / TCP # kerberos Encrypted Rlogin
#
# Unofficial But Necessary (for Netbsd) Services
#
Supfilesrv 871 / TCP # SUP Server
SupfiledBG 1127 / TCP # sup debugging
#
# DataGram Delivery Protocol Services
#
RTMP 1 / DDP # Routing Table Maintenance Protocol
NBP 2 / DDP # name Binding Protocol
Echo 4 / DDP # AppleTalk Echo Protocol
ZIP 6 / DDP # zone information protocol
#
# Services Added for the debian GNU / Linux Distribution
Poppassd 106 / TCP # eudora
Poppassd 106 / UDP # eudora
Mailq 174 / TCP # mailer transport queue for zmailer
Mailq 174 / TCP # mailer transport queue for zmailer
SSMTP 465 / TCP # SMTP OVER SSL
GDOMAP 538 / TCP # gnustep distributed Objectsgdomap 538 / udp # gnustep distributed objects
SNEWS 563 / TCP # NNTP over SSL
SSL-LDAP 636 / TCP # LDAP over SSL
Omirr 808 / TCP Omirrd # Online Mirror
Chapter 6 Berkeley Socket - 177 -
Omirr 808 / UDP Omirrd # Online Mirror
Rsync 873 / TCP # rsync
Rsync 873 / udp # rsync
SIMAP 993 / TCP # IMAP over SSL
SPOP3 995 / TCP # POP-3 over SSL
Socks 1080 / TCP # Socks Proxy Server
Socks 1080 / UDP # SOCKS Proxy Server
RMTCFG 1236 / TCP # Gracilis Packet Remote Config
Server
Xtel 1313 / TCP # French Minitel
Support 1529 / tcp # gnats
Cfinger 2003 / TCP # gnu finger
NINSTALL 2150 / TCP # Ninstall Service
NINSTALL 2150 / UDP # Ninstall Service
AfBackup 2988 / TCP # AfBackup System
AfBackup 2988 / UDP # AfBackup System
ICP 3130 / TCP # Internet Cache Protocol (Squid)
ICP 3130 / UDP # Internet Cache Protocol (Squid)
Postgres 5432 / TCP # Postgres
Postgres 5432 / udp # Postgres
Fax 4557 / TCP # Fax Transmission Service
(OLD)
Hylafax 4559 / TCP # Hylafax Client-Server Protocol
(New)
Noclog 5354 / TCP # Noclogd with TCP (NOCOL)
Noclog 5354 / UDP # Noclogd with udp (nocol)
Hostmon 5355 / TCP # Hostmon Uses TCP (NOCOL)
Hostmon 5355 / UDP # Hostmon Uses TCP (Nocol)
IRCD 6667 / TCP # Internet relay chat
Ircd 6667 / udp # Internet relay chat
Webcache 8080 / TCP # WWW CACHING Service
Webcache 8080 / UDP # WWW CACHING Service
TPROXY 8081 / TCP # Transparent Proxy
TPROXY 8081 / UDP # Transparent Proxy
Mandelspawn 9359 / udp mandelbrot # network mandelbrot
Amanda 10080 / UDP # Amanda Backup Services
Kamanda 10081 / TCP # Amanda Backup Services (Kerberos)
Kamanda 10081 / UDP # Amanda Backup Services (Kerberos)
Amandaidx 10082 / TCP # Amanda Backup Services
Amidxtape 10083 / TCP # Amanda Backup Services
- 178 - Linux network programming
ISDNLOG 20011 / TCP # isdn logging systemisdnlog 20011 / udp # isdn logging system
VBOXD 20012 / TCP # Voice Box System
Vboxd 20012 / UDP # Voice Box System
Binkp 24554 / tcp # Binkley
Binkp 24554 / udp # Binkley
ASP 27374 / TCP # Address Search Protocol
ASP 27374 / UDP # Address Search Protocol
TFIDO 60177 / TCP # ifmail
TFIDO 60177 / UDP # ifmail
FIDO 60179 / TCP # ifmail
FIDO 60179 / UDP # ifmail
# Local Services
LinuxConf 98 / TCP
Swat 901 / TCP # add swat service used via inetd
[root @ bbs / etc] #
Below, we will see what this list is explained in an example of the port 80 of Web Server? :
It is this like this in the Services file:
WWW 80 / TCP http # WorldwideWeb HTTP
You can see this line of this line 3:
l WWW represents the port name of the HTTP protocol (that is, the default Web Browser connection server
mouth).
L 80 / TCP This part is separated by "/", the first half is indicated by the port number (HTTP here)
The port of the protocol is 80), and the second half is represented by a TCP connection (that is, the connection of the connection, corresponding is
UDP).
l The HTTP representative is an HTTP protocol.
L # WorldwideWeb http Finally, this is a "#" header, it is some comments.
We are in fact only HTTP and 80. Through this rule, everyone can see this redhat 6.0
The reserved port (which includes some ports greater than 1024)
This file only defines the ports and its alias for each service. If you run
$ telnet 127.0.0.1 www
Then you connect to the local web server (of course, the premise is that you have already launched this web service.
.
You should try to avoid the ports and systems of your server and the Services files used by your servers.
The declared port overlaps. Avoiding the method except for the reference system's Services file, you can also directly
Telnet is tested.
For example, your program wants to use the 4000 port to listen to the network connection, you can use the program for use
4000 ports, you can do this like this:
$ telnet 127.0.0.1 4000
Chapter 6 Berkeley Socket - 179 -
If the system gives an error message:
[root @ bbs / etc] # telnet 127.0.0.1 4000
Trying 127.0.0.1 ...
Telnet: Unable to connect to Remote Host: Connection Refused
Then explain that there is no program in the system to use 4000 ports, you can use it with confidence.
Tips: If you write a Server and Client, but the client can't connect to Server and you don't know where it is.
When you have any questions, you can use the system's tool Telnet to help you. If your Server listening is 4000, you can use Telnet to connect to 4000 ports directly. If you use a Telnet connection, then you can determine that your Server is running properly.
6.10 five I / O modes
Below we briefly introduce a variety of I / O mode of operation. Under Linux / Unix, there are five I / O exercises below
Mode:
l blocking I / O
l Non-blocking I / O
L I / O multiplex
l Signal Drive I / O (SIGIO)
l Asynchronous I / O
This chapter tells some details of I / O, you can skip this part when you read it, then in the second time
Read this section when you read this book.
In general, there are two steps on the input operation:
1. Waiting for data to read
2. Copy the data from the system kernel to the program's data area.
For an input operation for a socket, the first step is generally waiting for data from the network to the local. Plural
When the package arrives, the data will be copied from the network layer to the kernel; the second step is to copy data from the kernel.
In the data area of the program.
6.10.1 blocking I / O mode
Blocking I / O mode is the most commonly used I / O mode. Most programs are all I / O of the blocking mode. lack
The mode in which a socket is established is to block the I / O mode.
For a UDP socket, the data ready is relatively simple:
l I have received a whole datagram.
l did not receive it.
The concept of TCP is more complicated, and some other variables are needed.
In Figure 6-4, a process calls the recvfrom, and then the system call does not return to know that there is a data report to the local
The system then copies the data to the cache of the process. (If the system calls receive an interrupt signal, it's
Call will be interrupted)
We call this process in calling Recvfrom until returning from Recvfrom is blocked. When Recvfrom
When returned normally, our process continues its operation.
- 180 - Linux network programming
Figure 6-4 Simple example of TCP connection
6.10.2 Non-blocking mode I / O
When we set a socket to non-blocking mode, we are equivalent to telling the system kernel: "When I ask for
I / O operations cannot be completed immediately. When you want my process to sleep, don't do this, please return it right away.
Go back to me. "
We can refer to Figures 6-5 to describe the non-blocking mode I / O.
We started three calls to Recvfrom, because the system has not received network data, so the kernel immediately returns
Back to an EWOULDBLOCK error. Fourth time we call the Recvfrom function, a datagon has arrived,
The kernel copies it into the buffer of our application, then the recvfrom returns it, we can receive it.
The data is processed.
When an app uses a socket of non-blocking mode, it needs to use a loop to be tested.
A file descriptor has data readable (called POLLING). The application keeps the POLLING core to check if I / O
The operation is ready. This will be a very waste of CPU resources. This mode is not very common in use.
Chapter 6 Berkeley Socket - 181 -
Figure 6-5 Non-blocking mode I / O
6.10.3 I / O multiplex
When using I / O multi-channel technology, we call the select () function and the poll () function, when calling them
Blocking instead of us to block when retivfrom (or RECV). Figure 6-6 illustrates its working mode.
When we call the SELECT function to block, the SELECT function waits for the data settlement to enter the read ready state. When the SELECT function returns, the socket can read the data. At this time, we can call Recvfrom.
The function copies the data into our program buffer.
Compared with blocking mode, SELECT () and poll () have no advanced places, and only need in blocking mode.
To call a function: read or send, after using multiple multiplexing technology, we need to call two functions: first
Call the select () function or a poll () function before you can perform real read and write.
Advanced with multiple multiplexing is that it can wait for multiple file descriptors at the same time, and these file descriptors (set
Word Descriptor) Any one of them enters the read ready state, the select () function can return.
- 182 - Linux network programming
Figure 6-6 I / O multiplexing
Suppose we run a network client program, to handle the network data from the sockets at the same time, to handle local
Standard input and output. When our program is obstructing data waiting for the standard, if the server is
The program was killed by Kill (or Down), then the server-end TCP protocol will give the client (we end)
The TCP protocol sends a FIN data representative to terminate the connection. But our program blocks the number of waiting for standard input
According to it, it does not see the end sign before it reads the socket data (maybe for a long time). We will then
The socket of the blocking mode cannot be used.
IO multiple technology is generally used in these situations:
l When a client needs to process the input and output operations of multiple file descriptors simultaneously (generally
Standard input and network sockets), I / O multiplexing technologies will have a chance to be used.
l When the program needs to perform multiple sockets operations at the same time.
l If a TCP server program handles the socket that is listening to the network and has been connected
Tag.
l If a server program uses TCP and UDP protocols simultaneously.
l If a server uses a variety of services at the same time and each service may use different protocols (such as inetd
That's it).
I / O multi-service technology is not only limited to the network program application. Almost all programs can find I / O
Multiplexed places.
6.10.4 Signal Drive I / O
We can use the signal to let us know when the kernel uses the SIGIO signal when the file descriptor is ready. I
They refer to this mode called signal driver I / O mode.
Using this model, we first need to allow sockets to use signal driver I / O, but also install a SIGIO
Chapter 6 Berkeley Socket - 183 -
Processing function. In this mode, the system call will return immediately, then our program can continue to do other things.
situation. When the data is ready, the system sends a SIGIO signal to our process. This way we can be in SIGIO
The I / O operation is performed in the processing function of the signal (or we notify the main function in the function with data readable).
We don't have to do too much understanding of the SIGIO signal processing function (in the next chapter we will introduce the signal.
Related content). For signal driver I / O mode, its advanced is that it will not block when it is waiting for data.
The order can be your own thing. When there is a data arrival, the system core will send a SIGIO signal to the program.
Notification, so our program can get greater flexibility, because we don't have to make additional data for additional data
code.
Figure 6-7 Signal drive I / O
Signal I / O allows the kernel to signal us when a file descriptor changes. asynchronous
I / O can improve the efficiency of our program for I / O reading and writing. By using it, when our program is performed for I / O operation, the kernel can return immediately after initializing the I / O operation, while the I / O operation is performed, our program can do
Your own thing, until the I / O operation ends, the system core is sent to our program message notification.
Socket Signal Drive I / O Use Signal SIGIO Based on Berkeley Interface. Some system sigpoll signals,
It is also equivalent to SIGIO.
In order to use a signal driver I / O operation on a socket, the following three steps must be.
(1) The processing function of one and SIGIO signal must be set.
(2) The owner of the socket must be set. Generally, it is used to use the F_Setown parameter of the FCNTL function.
Set the owner.
(3) Sockets must be allowed to use asynchronous I / O. Generally, by calling the f_setfl command of the FCNTL function,
O_async is implemented for parameters.
Note: We must set the SIGIO signal processing function before setting the homework, SIGIO's default action is ignored.
slightly. So if we call these two function calls in the opposite order, then after the FCNTL function calls, the Signal function calls
- 184 - Linux network programming
A small period of time may receive a SIGIO signal. In that case, the signal will be discarded. In the SVR4 system, SIGIO is
To ensure the call sequence of these two functions: first modify the Signal to set the SIGIO signal processing function, then use the FCNTL function settings
The home of the socket.
Although the setting sleeve is very simple in asynchronous I / O, how difficult to use it is how to break in the program
When the SIGIO signal is sent to the socket, what is the state?
1. UDP socket SIGIO signal
Use asynchronous I / O on the UDP protocol. This signal will be generated at this time:
The L socket has received a packet of a datagram.
l The socket has an asynchronous error.
When we use UDP sockets I / O, we use the recvfrom () function to read the number of data.
According to or asynchronous I / O error message.
2. SIGIO signal for TCP socket
Unfortunately, asynchronous I / O is almost no role in TCP sockets. Because for a TCP set
Word, the number of SIGIO signals is too high, so the SIGIO signal can't tell us what happened.
What is things. In TCP connections, SIGIO signals will be generated at this time:
l The successful establishment of a new connection on a socket that monitors a port.
l The request for a broken line is successfully initialized.
l The success of a disconnection request.
l Some channels of sockets (send channels or reception channels) are turned off.
l Skats receive new data.
l Skating sends the data out.
l A error occurred in an asynchronous I / O.
For example, if a TCP socket that is performing a read and write operation is in the signal driver I / O state, then
Whenever the new data arrives locally, a SIGIO signal will be generated, and each time the local socket is far from
After confirmation, a SIGIO signal is also generated. For our programs, it is unable to distinguish these two SIGIOs.
What is the difference. In this case, use SIGIO, the TCP socket should be set to block one without blocking mode.
Blocked READ and WRITE (RECV and SEND) operations. We can consider using asynchronous I / O on a socket that only monitors network connection operations, so when there is a new connection, the SIGIO signal will be generated.
A more practical aspect of a signal driver I / O is NTP (Network Time Protocol Network Time Protocol)
Server, it uses UDP. The primary cycle of this server is used to receive a data report packet sent from the client.
Then send a request. For this server, it is important to receive the specific time of each packet under records.
Because that will be the value returned to the client, the client wants to use this data to calculate the datagram to return to the network.
time. Figure 6-8 shows how such a UDP server is established.
Chapter 6 Berkeley Socket - 185 -
Figure 6-8 NTP server
Most UDP services are designed to map the pattern on the left. But the NTP server uses the technology of the right
Surgery. When there is a new datagram, the SIGIO's handler will take out it in a program waiting to be read.
The queue, the main program reads data from this queue. Although this will increase the length of the program code, it can
Get the exact time to reach the server program.
6.10.5 Asynchronous I / O
When we run in asynchronous I / O mode, if we want to perform I / O operation, just tell the core us to
Perform I / O operation, then the kernel will return immediately. The specific I / O and data copies are completed by the kernel, we
The program can continue to be executed down. When the kernel completes all I / O operations and data copies, the kernel will inform us.
program.
The difference between asynchronous I / O and signal driver I / O is:
l Signal driver I / O mode, the kernel notifies us the application to send us when the operation can be operated.
SIGIO message.
l In asynchronous I / O mode, the kernel will notify us after all operations have been completed by the kernel operation.
application.
As shown below, when we perform an IO operation, we pass our file descriptor, we
The size of the cache pointer and the size of the cache, one offset OFFSET, and after the end of the kernel
System method. This call is also returned immediately, and our programs do not need to block the ready of the data waiting. we
You can ask the system core after all the operations (including reading information from the network, then copying to us)
The kernel's cache area sent us a message.
- 186 - Linux network programming
Figure 6-9 Asynchronous I / O
6.10.6 Comparison of Several I / O modes
The following table is compared to these I / O modes.
Table 6-1 Comparison of several I / O modes
Blocking mode Non-blocking mode I / O multi-channel multiplexed signal driver I / O asynchronous I / O
initialization
end
an examination
an examination
an examination
an examination
an examination
an examination
an examination
an examination
an examination
end
an examination
Ready
initialization
end
Signal notification
initialization
end
initialization
Signal notification
We can clearly see the differences in each model, and your program can choose the appropriate mode to use.
6.10.7 FCNTL () function
block. You should understand what it means. Simply put, blocking is the synonym of "sleep". You may notice
block
wait
data
Put data
From kernel
Copy
User-run
sequence
Chapter 6 Berkeley Socket - 187 -
When you run the above Listener, it is just simply waiting for receiving data. It calls RECVFROM ()
When the function, but that time (Listener calls the RECVFROM () function), it is not available to receive. and so
The Recvfrom () function is blocked there (that is, the program is stopped at the recvfrom () function) until there is data pass. Many functions can be blocked. Like the accept () function is blocking, all functions starting with RECV are also blocked.
of. The reason why they do is what they need to do.
When you set a socket descriptor at first, the system kernel is set to block the state. If you don't
I want your socket descriptor to be in a blocking state, then you can use the function FCNTL ().
The FCNTL () function declaration is as follows:
#include
#include
INT FCNTL (INT FD, INT CMD, Long Arg);
Let's take a segment of a segment:
#include
#include
Sockfd = Socket (AF_INET, SOCK_STREAM, 0);
FCNTL (SOCKFD, F_SETFL, O_NONBLOCK);
??
??
This allows a socket to be set to a blockless mode, you can effectively "detect" on the socket descriptor. Such as
If you try to read data from a socket descriptor without receiving any data, then read
Take a function will return to -1 representative errors, the value in Errno in Errno is EWouldBlock.
In general, this non-blocking mode is not a good choice in some cases. If your program has not been
Received the data passed, then your program will perform non-stop loop to check if there is data arrival, waste
A large number of CPU times, and these CPUs can do other things.
Another method of detecting a socket descriptor is to call the Select () function.
6.10.8 Socket Select SELECT () Function
This technology has a little strange but it is really useful to our program.
Imagine the following situation:
The server you wrote to listen to the client's connection, but you also want to connect from you before you have established.
Come to read data. You may say: "There is no problem, I don't just need to use an Accept () function and a pair of RECV ()
Function? "Don't worry, you have to think about it, when you call the accept () function to block, you can call RECV ()
Function? "Use non-block sockets!" You may say this. Yes, you can. But if you don't want to wave
What should I do if I expensive CPU time?
SELECT () function can help you monitor many sockets simultaneously. It will tell you which socket is already available
Data, which socket can already be written to data, even you can know which socket has an error, if you want
If you know.
The following is a declaration of the select () function:
- 188 - Linux network programming
#include
#include
#include
INT SELECT (int Numfds, fd_set * readfds, fd_set * writefds,
FD_SET * EXCEPTFDS, STRUCT TIMEVAL * TIMEOUT
The following is the parameter description of the select () function:
l Numfds is the largest number in the FD collection in the FD collection in the FD set in the FD set in the FD set in ExceptFDs.
1.
l The FD collection in readfds will be monitored by SELECT to be read.
l WriteFDs' fds collection will be monitored by SELECT to monitor whether it can be written. l ExceptFDs The FDS collection will be monitored by SELECT to monitor the exception.
If you want to know if you can read data from standard input and some socket (SOCKFD), you can
Add file descriptors and sockfd to ReadFDs. Numfds' value is set to the largest in the file descriptor in the readfds.
That plus one, that is, SOCKFD 1 (because the value of the file descriptor is 0, any other text
The descriptor is larger than the file descriptor input by the standard.
When the select () function returns, readfds will be modified to tell you which file descriptor you can use.
To read data. Using the fd_isset () macro, you can select the result of the select () function.
Let's take a look at how to deal with these FD_SETs before making a deeper operation. The following macros can be specially entered
Well this type of operation:
l fd_zero (fd_set * set) Clear a file descriptor collection
l fd_set (int FD, FD_SET * SET) Adds the file descriptor FD to the set set.
l FD_CLR (int FD, fd_set * set) Remove the file descriptor FD from the collection set.
l FD_Isset (int FD, fd_set * set) Test file descriptor FD exists in the file descriptor set.
So what is STRUCT TIMEVAL? This is the case, in general, if there is no file descriptor to meet
Your request, your program doesn't want to wait forever. Maybe you want to output information on the screen every 1 minute:
"Hello!". This representative time structure will allow you to define a timeout. In calling the select () function, if time
More than the length of time representative represented by the timevalval parameter, and there is no file descriptor to meet your requirements, then SELECT () letters
The number will return back to allow you to do the following.
This TimeVal structure is defined as follows:
Struct TimeVal
{
INT TV_SEC; / * seconds * /
INT TV_USEC; / * microsecond * /
}
Just set the TV_sec to you want to wait for the number of seconds, then set TV_USEC for the number of microseconds to wait (really
The time is the number of seconds represented by TV_sec plus the number of microseconds represented by TV_USEC). Note that it is microseconds (million points)
One) rather than milliseconds. One second has 1,000 milliseconds, one milliseconds have 1,000 microseconds. So, a second has 1,000,000 microseconds.
When the select () function returns, the time in TimeVal will be set to execute as SELECT () remains.
time.
Chapter 6 Berkeley Socket - 189 -
Now, we have a time consumption in microseconds! But because Linux is the same as Unix, the smallest
The time film is 100 microseconds, so no matter how small the TV_USEC is set, the minimum unit of the timer is 100
Microseconds.
It is also necessary to pay attention to:
l If you set the struct timeval to 0, the select () function will return immediately, return to you.
The status of the file descriptor in the collection.
l If you set the Timeout parameter to NULL, the select () function enters the blocking state, except for waiting
Status changes to the file descriptor, otherwise the SELECT () function will not return. The following code demonstrates that the input is waiting for 2.5 seconds from the standard input.
#include
#include
#include
/ * Number of file descriptors for standard input * /
#define stdin 0
Main ()
{
Struct TimeVal TV;
FD_SET READFDS;
/ * Set waiting time is 2 seconds zero 500,000 microseconds * /
TV.tv_sec = 2;
TV.TV_USEC = 500000;
FD_ZERO (& ReadFDs);
FD_SET (stdin, & readfds);
/ * Because we just want to wait for input, set WRITEFDS and EXECEPTFDS to null * /
/ * The program will wait for 2 seconds to 500,000 microseconds here, unless the standard input is operated during this time * /
SELECT (stdin 1, & readfds, null, null, & TV);
/ * Test if stdin is in the ReadFDS collection * /
IF (fd_isset (stdin, & readfds))
{
/ *, Then there is input * /
Printf ("a key was press! / n");
}
Else
{/ * Does not, then there is no input * /
- 190 - Linux network programming
Printf ("TIMED OUT./N");
}
}
On standard input, you need to enter the Enter the terminal will pass the input information to your program. So if you
If you don't enter your own return, the program will wait until the timeout.
The last point you need to pay attention to the select () function: If your socket descriptor is listening through the listen () function
Wait for an external network connection, you can use the select () function (add the socket descriptor to the ReadFDS collection
Middle) to test whether there is an unprocessed new connection.
The above is some brief introduction to the select () function.
6.11 external data
Many transport layers support out-of-band data, sometimes called fast data (Expedited
DATA). The reason why there is an external data is because sometimes it is "fast" to tell the terminal.
There are some information on the other side of the network. This "fast" means our "prompt" information will be in normal network
Data (sometimes referred to as the in-band data) before reaching the end of the other side. This illustrates
It has a high priority than the general data. But don't think that the external data is implemented by two socket connections. thing
In fact, the external data is also transmitted by a connection.
Unfortunately, almost every transport layer has different processing methods for extracted data. We have studied TCP below
Out of the model of the model, provide a small example to see how it handles the out-of-band data, and the call set
Method of launching an API.
The abstraction of the stream socket includes the concept of external data, with external data is connected to each pair of streams.
Logical independent transmission channels. The external data is transmitted to the user independently of ordinary data, this abstract requirement
The data device must support at least one out-of-band data message per hour is reliably transmitted. This news may contain at least
One byte; and only one out-of-band data information is waiting for transmission. For communication only supports data
For the agreement, for example, emergency data is sent to normal data in the same sequence), the system usually put emergency data from Pu
Separation in the data is separated separately. This allows the user to make a selection between emergency data and inseparable reception of emergency data (in the order of sequential reception). In this case, the user also
Can "peek" emergency data.
A application may also like to deal with emergency data in the line, that is, as part of the normal data stream. This
It can be implemented by setting SO_OBINLINE in the socket option. In this case, the application may hope
Determine which of the unread data is "emergency" ("emergency" term is usually applied to outside the line). for
With this purpose, in the implementation of Sockets, you must reserve a logical mark in the data stream to indicate the external data from
Which point starts to send.
SELECT () function can be used to process notifications from external data.
6.11.1 External Data of TCP
There is no "external data" in the TCP. TCP is passed by a method called "emergency mode"
In addition to data. Suppose a process writes N-bytes of data to a TCP socket, and the data is tcp
The transmit buffer cache of the terminal is waiting to be sent to the network. We can see the arrangement of data in Figure 6-10.
Chapter 6 Berkeley Socket - 191 -
Figure 6-10 Arrangement of TCP data
The process now writes a single-byte "out-of-band data" using the send () function of MSG_OOB as a parameter.
Includes an ASCII character "a":
Send (fd, "a", 1, msg_oob);
TCP places data in the next available transmission buffer and sets the "emergency pointer" of this connection (Urgent
Points point to the next available buffer space. Figure 6-11 shows the state we describe, and will bring external
According to OUT-OF-BAND, it is expressed as "OOB".
Figure 6-11 ODB data
The point to the TCP's emergency pointer is the OOB data sent by the program.
From the state of the TCP socket represented by Figure 6-11, it is known that the next data to be transmitted is the URG of TCP.
(Urgent Pointer) logo, send the URG flag, TCP will only send the byte of the extracted data below.
However, in the data sent by TCP, only the URG flag of TCP may contain the TCP, but there is no contained we send
OOB data. Does this happen to depends on the data queue that TCP will send, in OOB data
How much is the previous data. If the data before OOB has been filled in one transmission, the TCP will only send
Send URG logo, do not send OOB data
This is an important feature of a TCP emergency data state: TCP information head pointed out that the sender entered an emergency mode (ratio
Fang said that the URG flag is set at the emergency offset), but the data at the emergency offset is not necessary to send it.
go with. In fact, if the stream of TCP socket is stopped (may be the receiving buffer of the receiver socket
Without a spare space), in order to send out external data, the system will send a TCP packet that does not contain data, indicating this
It is an outgoing data. This is also a favorable point in our use of external data: TCP connection is not to the other party
- 192 - Linux network programming
When sending data, a signal of an extracted data can also be sent.
If we send a multi-byte out-of-band data like this:
Send (FD, "ABC", 3, MSG_OOB);
In this example, TCP's emergency pointer points to the last bit of the data, so only the last bit data ("c") is only considered "out-of-band data".
We have roughly understand how the sender sent "external data". Let's take a look at the recipient.
How to receive "external data".
1. When the TCP receives a data segment containing the URG flag, TCP checks "emergency pointer" to verify it is
No Data referred to in the emergency pointer has reached the local. That is, no matter whether it is TCP emergency mode from the sender.
The first transmission of the receiver is transmitted. In general, TCP transmission data is divided into many small packets to transmit
(The arrival time of each package is also different). There may be several packets in several packets, but in these packages
The emergency pointer is pointing to the same location, that is, multiple emergency pointers point to a data. have to be aware of is,
For this extra data, although there are multiple poke points to it, only the first emergency pointer will notify the program.
2. The condition for receiving the process received another detailed data is: there is another pointer to external data to
Reach. Note that this is a pointer of "another out-of-band data", not the other of the "an outgoing data"
pointer. First, the SIGURG signal is sent back to the host of the socket, which depends on whether the FCNTL () function has been used.
Or IOCTL () function sets the primary and this program to the specific operation function of the SIGURG signal. Secondly, if
A program is blocking the call to the SELECT () function of this socket descriptor, the select () function generates one
Exception, then return.
Note: When the process receives notifications of external data, it does not care whether the true data of the external data arrives.
3. When the real out-of-external data referred to by the emergency pointer arrives at the receiving end through the TCP network, data or
Put it into an out-of-band data buffer or just a simple and normal network data. Under the default conditions,
The SO_OOBINLINE socket option is not set, so this single-byte out-of-external data is not prevented.
In the receiving cache area of the socket, it is placed in a separate out-of-band data buffer belonging to this socket. Such as
If this process wants to read the specific content of this extra data, the only way is to call RECV, Recvfrom,
Or the Recvmsg function, and must specify the MSG_oob flag.
4. If a process sets the socket to the SO_OOBINLINE property, it is referred to by the emergency pointer.
The byte of the external data will be placed on the left side of the normal socket buffer. In this case, the process cannot be
Specify MSG_oob to read the out-of-band data of this byte, but it can know the arrival time of the external data:
By checking the out-of-band data tag of the socket.
Some errors that may happen:
5. If the process is not sent to the external data (for example, by msg_oob)
The parameter is used to receive a function), and EinVal will be returned.
6. When the real out-of-external data arrives, the process is notified (SIGURG or SELECT function)
The external data arrives (that is, the notification signal of the external data has arrived), if the process tries to read the external data, then
Return EWOULDFBLOCK. The process can do just to read the receiving cache area of the socket. (Maybe, due to
The data of the buffer area is full, the byte information of the external data cannot be transferred, so maybe you need to clean it.
The receiving cache area is sent to the out-of-band data to empty some space) 7. If the process tries to read the same outgoing data multiple times, EinVal will be returned.
8. If the process sets the socket property to SO_OOBINLINE, then try to pass the specified MSG_oob
Chapter 6 Berkeley Socket - 193 -
The flag will be read out, and EINVAL will be returned.
Below we will make some changes in the previous socket routines to test the send and receive of the external data.
6.11.2 OOB Transmission Socket Socket Routine (Server Code Server.c)
#include
#include
#include
#include
#include
#include
#include
#include
/ * The local port * / server to listen to * /
#define myport 4000
/ * How much does it accept at the same time without Accept's connection * /
#define backlog 10
Void
SIG_URG (int Signo);
Main ()
{
/ * Listening on Sock_FD, new_fd accepts new connections * /
INT SOCK_FD, New_FD;
/ * The variable used to store the default SIGURL processor for previous systems * / void * Old_sig_urg_handle;
/ * Your address information * /
Struct SockAddr_in my_addr;
/ * Connector's address information * /
Struct SockAddr_in their_addr;
INT SIN_SIZE;
Int n;
CHAR BUFF [100];
/ * Here is the error check we have always emphasized. Returns * / if you call socket () error
IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) == -1)
{
- 194 - Linux network programming
/ * Output error prompt and exit * /
PERROR ("socket");
Exit (1);
}
/ * Host byte order * /
MY_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
MY_ADDR.SIN_PORT = HTONS (MyPort);
/ * Pack the IP of the running program machine into S_ADDR * /
MY_ADDR.SIN_ADDR.S_ADDR = INADDR_ANY
/ * Clear the remaining space of this structure * /
Bzero (& (My_ADDR.SIN_ZERO, 8);
/ * Here is the wrong check we have always emphasized! ! * / if (Bind (SockFD, (Struct SockAddr *) & my_addr,
SIZEOF (STRUCT SOCKADDR) == -1)
{
/ * If you call bind () fail, give an error message, exit * /
PERROR ("bind");
Exit (1);
}
/ * Here is the wrong check we have always emphasized! ! * /
IF (Listen (Sockfd, Backlog) == -1)
{
/ * If you call Listen fail, give an error prompt, exit * /
PERROR ("listen");
Exit (1);
}
/ * Set up SIGURG's processing function SIG_URG * /
Old_sig_urg_handle = signal (sigurg, sig_urg); / * Change the host of Connfd * /
FCNTL (SockFD, F_Setown, getPid ());
While (1)
{
Chapter 6 Berkeley Socket - 195 -
/ * Here is the primary accept () loop * /
SIN_SIZE = SIZEOF (struct sockaddr_in);
/ * Here is the wrong check we have always emphasized! ! * /
IF ((new_fd = accept (sockfd, (struct socaddr *) & their_addr, & sin_size)) == -1)
{
/ * If an error occurs when you call accept (), an error message is given to enter the next loop * /
PERROR ("accept");
CONTINUE;
}
/ * The server gives the information that appears * /
Printf ("Server: Got Connection FROM% S / N", INET_NTOA (THEIR_ADDR.SIN_ADDR);
/ * Here will create a child process to communicate with the socket that has just been established. * /
IF (! fork ())
/ * Here is a child process * /
While (1)
{
IF ((N = RECV (new_fd, buff, sizeof (buff) -1)) == 0)
{
Printf ("ReceiveD EOF / N");
Break;
}
BUFF [N] = 0;
Printf ("RECV% D Bytes:% S / N", N, BUFF);
}
/ * Close this socket connection represented by New_FD * /
Close (new_fd);
}
}
/ * Waiting for all child processes to exit * /
While (Waitpid (-1, null, wnohang> 0);
/ * Recovery system previously pair of SIGURG's processor * /
Signal (Sigurg, Old_sig_urg_handle);
}
Void
SIG_URG (int Signo)
{
- 196 - Linux network programming
Int n;
CHAR BUFF [100];
Printf ("Sigurg ReceiveD / N");
N = RECV (New_FD, BUFF, SIZEOF (BUFF) - 1, MSG_OOB;
BUFF [N] = 0;
Printf ("Recv% D OOB BYTE:% S / N", N, BUFF;
}
6.1.1.3 OOB Transmission Socket Socket Routine (Client Code Client.c)
Below is the client program:
#include
#include
#include
#include
#include
#include
#include
#include
/ * The port number of the server program listener * /
#define port 4000
/ * We can receive the maximum number of bytes available once * /
#define maxDataSize 100int
Main (int Argc, char * argv [])
{
/ * Socket descriptor * /
Int Sockfd, Numbytes;
Char buf [maxdatasize];
Struct hostent * he;
/ * Host information of the connector * /
Struct SockAddr_in their_addr;
/ * Check parameter information * /
IF (argc! = 2)
{
Chapter 6 Berkeley Socket - 197 -
/ * If there is no parameters, it will give it to the usage method * /
FPRINTF (stderr, "usage: client hostname / n");
Exit (1);
}
/ * Acquired host information * /
IF ((he = gethostByname) == null)
/ * If a getHostByname () has an error, the error message is displayed and exits * /
Herror ("gethostbyname");
Exit (1);
}
IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) == -1) {
/ * If there is an error in Socket () call, the error message is displayed and exits * /
PERROR ("socket");
Exit (1);
}
/ * Host byte order * /
THEIR_ADDR.SIN_FAMILY = AF_INET;
/ * Network byte order, short integer * /
THEIR_ADDR.SIN_PORT = HTONS (port);
THEIR_ADDR.SIN_ADDR = * (Struct In_Addr *) He-> h_addr);
/ * Clear part left in the structure * /
Bzero (& (THEIR_ADDR.SIN_ZERO, 8);
IF (Connect (Sockfd, Struct SockAddr *) & their_addr, sizeof (struct sockaddr)) == -1)
{
/ * If connection error is established, an error message is displayed, exit * /
PERROR ("Connect");
Exit (1);
}
/ * Here is the error check! * /
IF (send (new_fd, "123", 3, 0) == -1)
{
/ * If it is wrong, give an error prompt, then close this new connection, exit * /
PERROR ("Send");
Close (new_fd);
- 198 - Linux network programming
exit (0);
}
Printf ("Send 3 Byte Of Normal Data / N");
/ * Sleep 1 second * /
Sleep (1);
IF (send (new_fd, "4", 1, msg_oob) == -1)
{
PERROR ("Send");
Close (new_fd);
exit (0);
}
Printf ("Send 1 Byte OOB Data / N);
Sleep (1);
IF (send (new_fd, "56", 2, 0) == -1)
{
PERROR ("Send");
Close (new_fd);
exit (0);
}
Printf ("Send 2 Bytes Of Normal Data / N");
Sleep (1);
IF (send (new_fd, "7", 1, msg_oob) == -1) {
PERROR ("Send");
Close (new_fd);
exit (0);
}
Printf ("Send 1 Byte OOB Data / N);
Sleep (1);
IF (send (new_fd, "89", 2, msg_oob) == -1)
{
PERROR ("Send");
Close (new_fd);
exit (0);
}
Printf ("Send 2 Bytes Of Normal Data / N");
Sleep (1);
Chapter 6 Berkeley Socket - 199 -
Close (SockFD);
Return 0;
}
6.11.4 Compilation Example
Note: You obviously need to start Server before running the client. Otherwise, the Client will perform an error (display "Connection
Refused ").
When there is only one connection (because this server is a multi-process, if there are multiple connections while existing
It may cause the screen output to be confusing), you can get the following results: (Note is to use the client program below to connect
Connected, and assume that you run our server program is on the local machine)
Root @ bbs # gcc -o server server.c
Root @ bbs # gcc -o client client.c
Root @ bbs # ./server
Root @ bbs # ./client 127.0.0.1
Send 3 Bytes of Normal Data <- Client Output
Recv 3 bytes: 123 <- Server output
Send 1 Byte of Oob Data <- Client Output
Sigurg Received <- Server Output
RECV 1 OOB BYTE: 4 <- Server Output
Send 2 Bytes of Normal Data <- Client Output
Recv 2 bytes: 56 <- Server output
Send 1 Byte of Oob Data <- Client Output
Sigurg Received <- Server Output
RECV 1 OOB BYTE: 7 <- Server Output
Received EOF <- Server Output
This result is what we want. The outgoing data sent by each client causes the server to generate
SIGURG signal, after receiving the SIGURG signal, the server side is read.
6.12 Using inetd (Internet Super Server)
6.12.1 Introduction
Using inetd to do network programming is a simple and stable design method, you don't need to consider complex
Socket programing. Your design work is almost completed after designing the communication agreement, the skills you need, only
For simple text analysis skills.
6.12.2 A simple inetd used server program Hello Inet Service
First, let's write a service program called Hello.
Hello.c
#include
#include
#include
- 200 - Linux network programming
Void main (void)
{
/ * As a general program, this printf will output to standard output * / printf ("Welcome! / N Hello! World! / N");
}
This app is simple, isn't it?
Compilation.
Root @ bbs $ gcc -o hello hello.c
Ok, now we already have the executable version of this program. If you execute this program directly,
There will be the following results:
Root@bbs# ./hello
Welcome!
Hello! World!
Root @ bbs #
Ah, the program writes the output, we have succeeded! note! What we need is the transmission operation on the network.
Now we can only show you some characters locally, we need to be able to transfer to the network
One end.
6.12.3 / etc / service and /etc/inetd.conf file
We must configure the system by setting two files: / etc / services and /etc/inetd.conf,
Thereby our Hello program becomes network accessible.
Let's take a look at how to set / etc / services and /etc/inetd.conf.
Let's take a test before we change the system / etc / services file, so that you can help readers
It has a clearer understanding.
We enter the following command on the local machine:
Root @ bbs # telnet localhost Hello
Hello: Bad Port Number
Note the error message given by the system: "Hello: BAD Port Number". Because the second parameter of the telnet command
It is a port we want to log in to the system, and we give Hello, the system does not know what port is Hello, so it said: "Wrong
Mrror port number.
So let's do this:
Add this line in / etc / services
Hello 20001 / TCP
It is a TCP connection in Port 20001.
When we go to this step, you can try again to give "Hello: Bad Port Number" wrong.
Error message:
Root @ bbs # Telnet Lcoalhost Hello
Trying 127.0.0.1 ...
Telnet: Unable to connect to Remote Host: Connection Refused
The information has changed: UNABLE TO Connect To Remote Host: Connection Refused.
Chapter 6 Berkeley Socket - 201 -
This shows that the system already knows which port representing the Hello (think we are above / etc / service file)
Specifies that Hello is a TCP connection, in 20001 port), but the system cannot establish a connection with the Hello port because
No procedure waits to wait for a connection in the number of 20001 ports.
OK, now we have already told the system what is the port of our Hello program, but when we connect hello
When the port is, the system has not performed our program. the following:
Add this line in /etc/inetd.conf:
Goodie Stream TCP NOWAIT ROOT / FULL_GOODIE_PATH_NAME / Goodie
The meaning of each parameter is
l Sock_Type has many species, mostly use stream / dgram.
l Proto generally uses TCP / UDP.
l Flagg has Wait / NOWAIT.
l User is that you specify that the program is to start with that user, this example is ROOT, if there is
Safety is considered, you should use Nobody. In general, it is recommended that you use low permissions, unless necessary, no
Open root use right.
l Server_Path and Args, this is the location of your service program and the number you want to join.
Next to restart inetd
Root @ bbs # killall inetd
Root @ bbs # inetd
Root @ bbs # _
This way we build a port 20001 Hello Service.
Now let's check if your good can perform:
Telnet Localhost 20001
or
Telnet your_host_name 20001
or
Telnet Locahost Hello
The result is as follows:
Trying 127.0.0.1 ...
Connected to Localhost.
Escape Character is '^)'.
Welcome!
Hello! World!
Root @ bbs # _
Yahoo !! We are now successful! ! It turns out that a simple, only two lines welcome information, no involvement
And a small program that is connected to any network, now you can use a network service! Very magical!
6.12.4 A complex inetd server program
Very simple? Letter do not believe you, Telnet / POP3 / IMAP / FTP is a service established by this way. when
- 202 - Linux network programming
However, Telnet / POP3 / IMAP / FTP services have complex command processing, and we now only display
Welcome, but at least we can make it a service program on the network. Below we now build
A small "network protocol", this agreement allows us to enter "exit", leave the program, while other instructions
They are all strings that are the same as input.
#include
#include
#include
Void main (void)
{
/ * Network accept buffer * /
Char BUF [1024];
/ * Whether to receive the flag of the exit string * /
Int OK;
/ * Output welcome information * /
Printf ("Welcome! This Is Hello Service! / N");
/ * Because the Linux / UNIX system has a cache, the FFLUSH function will immediately send the data in the cache.
Preventing the other side of the network connection cannot receive a small amount of data * /
Fflush (stdout);
/ * Initialize OK, set to not receive exit * /
OK = 0;
DO
/ * If the standard input has no data entry, the program is waiting for * /
While (FGETS (BUF, 1023, stdin) == null);
/ * Check if the current input is "exit" * / if (StrncaseCMP (BUF, "EXIT", 4) == 0)
{
/ * Set the flag * /
OK = 1;
/ * Send the received string of characters * /
Printf (BUF);
/ * Transmit the data in the cache to send * / fflush (stdout);
} while (!!);
}
Because inetd puts the input of the network as the standard input of the program, the output of the program as the network output,
Chapter 6 Berkeley Socket - 203 -
So the stdin in the program is equivalent to reading the network socket and stdout is equivalent to sending the network socket.
operating.
carried out:
Telnet Localhost Hello
or
Telnet your_host_name 20001
The results of the operation are as follows:
Trying 127.0.0.1 ...
Connected to Localhost.
Escape Character is '^)'.
Welcome! This is hello service!
Enter "Help"
Help
Help
Enter "EXIT"
exit
exit
Connection Closed by Foreign Host.
6.12.5 A more complex inetd server program
We can now have a simple handle to handle the network remotely, and the procedures do only
Is the operation of stdin and stdout! Below, we will design a slightly complex communication agreement, which is more
Used in general purposes.
#include
#include
#include
/ * Array of commands supported * /
Char * cmds [] = {"Help", "Say", "Hello", "Bye", "EXIT", NULL};
/ * Judging a string is the first few commands in the command array, if there is no existence, return -1 * /
INT getcmd (char * cmd)
{
INT n = 0;
While (cmds [n]! = NULL)
{
IF (StrncaseCMP (cmd, cmds [n], strlen (cmds [n])) == 0)
Return n;
N ;
} RETURN -1;
- 204 - Linux network programming
}
/ * Principal function * /
Void main (void)
{
/ * Cache area of the received command * /
Char BUF [1024];
/ * Whether to exit the sign of the command * /
Int OK;
/ * Output welcome information * /
Printf ("Welcome! This Is Hello Service! / N");
/ * Clear standard output cache * /
Fflush (stdout);
/ * Initial setting OK is not received with an exit command * /
OK = 0;
/ * Program main circulation body * /
DO
/ * If the program does not receive the input, loop waiting * /
While (FGETS (BUF, 1023, stdin) == null);
/ * After receiving the data, the command is determined * /
Switch (Getcmd (buf))
Case -1: Printf ("Unknown Command! / N"); Break;
Case 0: Printf ("How May I Help You, SIR? / N"); BREAK;
Case 1: Printf ("I Will Say% S", & BUF [3]); Break;
Case 2: Printf ("How're you doing Today? / n"); Break;
Case 3: Printf ("Si Ya, Mate! / N"); OK = 1; Break;
Case 4: Printf ("Go Ahead! / N"); OK = 1; Break;
}
/ * Clear output buffer * /
Fflush (stdout);} while (!!
}
Chapter 6 Berkeley Socket - 205 -
run:
Telnet Localhost Hello
or
Telnet your_host_name 2001
Try to enter "Help", "Say", "Hello", "BYE", "EXIT", etc., and others are not in command
The instructions in the column.
Ok, now we know, inetd is transformed into procedures whose standard output and standard input.
Network programs, this can greatly simplify our programming, avoiding what socket (), rv (), send () function
Deal.
6.12.6 Program must be observed by security guidelines
Note: When designing the inetd service, pay special attention to the problem of Buffer overflow (cache spillage),
This is also the following status:
Char buffer_overflow [64];
Fscanf (stdin, "% s", buffer_overflow);
Almost all security vulnerabilities have come.
You must not use this, no matter whether any reason, the same usage is not available. Hacker master can pass your
Buffer plug, then put into his own program coming in.
6.12.7 small knot
INETD services provided through the Linux system, we can easily write a network program and never to care.
Some of the skills that look highly difficult to understand. What you need to do is just written a normal read and write standard input.
Ordered, then configure the system inetd configuration file: / etc / service file and /etc/inetd.conf file.
6.13 This chapter summarizes
BSD UNIX introduces a socket abstraction as a mechanism, which allows applications to be soft in the operating system
Piece interface. Since many manufacturers adopt socket, socket interface has become a fact of fact.
A program calls the socket function creates a socket descriptor. The parameters called the Socket call indicated
Agreement and required servers. All TCP / IP protocols are part of the Internet protocol. System is socket
Created an internal data structure and fill in the protocol field, the system also uses the service type parameter to select a point
The protocol (often UDP or TCP).
Other system calls allow applications to indicate a local address (bind), forced socket enters passive mode
It is used to use (listen), or forced sockets to enter the active mode for a client to use (Connect). clothes
Worker can further use accept calls to get an access request (Accept), clients, and servers can send
Or receive data (READ or WRITE). Finally, after the end of a socket, the client and server can undo the connection.
Port (close).
Sockets have five I / O modes: blocking mode / non-blocking mode / IO multiplexing / signal driver IO / asynchronous
IO.
The external data is a method of another end computer information that can quickly notify the network. External data or even
You can only tell the remote computer to exist without having to transfer its specific data. External data is not built two
- 206 - Linux network programming
Connections to transmit data (not this in TCP), it is the so-called "out-of-band data" to existing
In the socket connection.
Few people want to write a web application, so the details of the process are best left to those who want to write. Practice and consult a large number of examples is the best way to start writing network code. But to master this technology but take a lot of time.