Berkeley Socket socket programming detailed explanation

xiaoxiao2021-03-06  102

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

The header file is defined as Sigpoll, and the default action of the SigPoll signal is to terminate this process. So we all

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 service_name is a name that needs to be present in the system service.

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.

转载请注明原文地址:https://www.9cbs.com/read-123743.html

New Post(0)