Network Program Design Sockets

zhaozj2021-02-08  239

About Socket programming, there is a simple introduction in "Linux from the entry into the proficiency", more detailed can be referred to "UNIX network programming volume 1: network API: socket and XTI 2nd edition" Tsinghua Yudyprint version, which also THREAD programming. A very good reference book, but no one translates it. Hu Shushu translated a "network programming", I collected it. If there is an update, please refer to Mr. Hu's personal homepage.

__________________________________________________________________________________________________________________

| Copyright Notice |

| | |

1, this article can be reproduced, modified, and reference, but please keep this statement and the original text of the future. |

| 2, in any case, the author and the translator's name cannot be deleted. |

| 3, in any case, this article cannot enter the business area. |

| | |

Hu Shushu |

| (husuyu@linux.cqi.com.cn) |

| | |

| November 1998 |

| _____________________________________________________________________________________

Chapter 59

table of Contents

Network program design

Ports (Ports) and sockets (Sockets)

Socket programming

Socket () System Call (System Call)

Bind () system call

Listen () system call

ACCEPT () system call

Setsockopt and GetSockOpt system call

CONNECT () system call

Program List 59.1 Server Side facing socket-oriented protocol

Program List 59.2 Client Function (The Lint Side Function)

ConnectionLESS socket programming

Program List 59.3 Service

note

Record and file lock (LOCKING)

Inter-process communication

summary

-------------------------------------------------- -----------------------------

- Chapter 59 -

Network program design

Author Kamran Husain, Tim Parker

Translator Hu Shusu

This chapter

Port and socket

Socket programming

Record and file lock

Inter-process communication

Read this chapter to have the basic concepts of the following network program design

Port and socket

Record and file lock

Inter-process communication

This article cannot be able to tell you all the contents of the network program design within a few pages. In fact, a first volume has

800 pages Specially designed a reference book for web programming is the most useful. If you really want to make network programming, you need a lot of experience in compiler, TCP / IP, and network operating systems. In addition, you still need to have great Patience.

For details of TCP / IP, see the << Self-study TCP / IP for 14 days from Tim Parker >> (SAMS Publish-

ING).

Port and socket

The network program design relies on socket acceptance and sending information. Despite the text of the socket, it seems to have some mysterious, but in fact

This concept is very easy to understand.

Most web applications use two protocols: Transfer Control Protocol (TCP) and User Packet Protocol (UDP). They all

Use a port number to identify the application. The port number is used by the program running on the host, so that you can pass the number.

Like the name to track each application. The port number makes the operating system easier to know how many applications are in use.

System, and which services are valid.

In theory, port numbers can be assigned by administrators on each host. But in order to better communications, some approximately

The protocol. These protocols enable the type of service requested to another system through the port number. Based on

Such reasons, most systems maintain a file containing port numbers and what services they provide.

The port number is allocated from 1. The port number is exceeded by the portion of 255 by the local host as a private purpose .1 to 255

The number used is used for the process and network services requested by the remote application. Each network communication is looped from the main computer

The TCP application layer. It is uniquely identified by two connected numbers. These two numbers set up a socket. Composition socket

The two numbers of the word are the IP addresses 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.

The IP address of the machine is unique. The port number is also unique in each machine, so the socket should be only in the network.

One. Such settings enables the two applications in the network to talk to each other based on sockets.

Send and receive machine maintain a port table, which lists all activated port numbers. Both machines include one into

Cheng is called binding, this is the entrance to each task, but it is just the opposite of the two machines. In other words, if a machine

The source port number is 23 and the destination port number is set to 25, then the source port number of the other machine is set to 25 destination port numbers.

Set up 23.

Socket programming

Linux supports Berkeley (BSD)-style socket programming. It also supports sockets for connection and non-connection types.

Server and clients are connected to the server and clients in the connection-oriented communication. No connection between the communication

According to a part of the information, it is exchanged. No matter that way, the server always starts, bind yourself (Banding)

) On a socket, then listen to information. How do the server try to listen to the connection set by your programming?

Type.

You need to know some system calls

Socket ()

Bind ()

Listen ()

accept ()

Setsockopt () and getsockopt ()

Connect ()

Sendto ()

Recvfrom ()

We will use these system calls in the following examples.

Socket () system call

Socket () system calls to create a socket for clients or servers, the socket function is defined below:

#include

#include

Int Socket (Int Family, Int Type, Int Protocol)

Family = af_Unix.type in Linux can be SOCK_STREAM it is reliable, although communication speed is slow,

Sock_dgram It is fast, but it is unreliable. If Type = SOCK_STREAM is then protocol = ipproto_

TCP. If Type = SOCK_DGRAM is then protocol = ipproto_udp.

If an error, the function will return -1. Otherwise, returns a socket descriptor you can pass in the call behind the program.

The text descriptor uses this socket.

There is no name when the socket is created. The client is read to write it with the name of the socket. This is to do the following binding function.

Things.

Bind () system call

The bind () system call assigns a name with a socket without the name. The binding function is defined in this:

#include #include

INT Bind (int Sockfd, Struct SockAddr * Saddr, Int Addrlen)

The first parameter is a socket descriptor. The second parameter is a structure used by the name. The third parameter is the structure

the size of.

Now you have already qualified an address for your client or server, you can connect () servers or serve

The device listens on. If your program is a server, then set it yourself to listen, wait for the connection. Let us come

See which functions can make you try to do this.

Listen () system call

Listen () system calls are used by the server. There is a definition below:

#include

#include

INT Listen (int Sockfd, int backlog);

Sockfd is a socket descriptor. The BackLog is a number that has not been decided in a time that is not decided to reject. General

Use the standard value 5. If an error occurs, the return value is less than 1.

If this call is successful, you can already be accepted.

ACCEPT () system call

Accept () call is used by the server to accept any information introduced from the client connect () call. must be understood

Yes, if it is not accepted, this function will not return any value. It is like this definition:

#include

#include

INT Accept (int Sockfd, Struct SockAddr * Peeraddr, Int Addrlen)

Other parameters and bind () system calls are the same except for PeeradDR to point to clients that issue a connection request.

On the basis of information introduction, the domain of the structure pointed to by PeeradDR is filled with respective values.

Setsockopt () and getsockopt () system call

The Socket library provided by Linux contains an error (this error "can not be re-enabled for a socket

Use the same port number, even after you get the socket, for example, you have written a server in one

Sockets wait for a program. The server opens the socket and listens on it is no problem. In any case, there are always some original

Because (whether it is normal or abnormal end procedures) makes your program need to restart. However, you can't put it after restarting.

It is bound to the original port. The error code returned from a bind () system call always reports that you try to connect

The mouth has been bound by another process.

The problem is that the Linux kernel never marks the port after the completion of a binding socket. In most UN

In the IX system, the port can be reused by a process, and can even be used by other processes.

Wrap the problem in Linux is, but the socket has been opened but not connected, using SetsockOpt

() System calls on it to set options (options) .SetSockOpt () call setting options and getSockopt () from a given

Sockets acquisition options.

Here is the syntax of these calls:

#include

#include

INT GetSockopt (int Sockfd, Int Level, Int Name

CHAR * VALUE, INT * OPTLEN

Int setsockopt (int Sockfd, Int Level, int name

CHAR * VALUE, INT * OPTLEN

Sockfd must be an open socket .level is the protocol standard used by the function (T

CP / IP protocol uses IPPROTO_TCP, socket standard options utility sol_socket), the name of the option (Name) is in the socket

The word manual is detailed. * Value points to the value or setsocko acquired by the getSockopt () function

The address of the value set by the PT () function .optlen pointer points to an integer, which contains the length of the parameter to byte.

Its value is set by getSockopt () and its value must be set by programmers when using one via setsockopt (). Options can be found in the second section of SetSockopt in the manual (SetsockOpt (2)).

Now let's go back to Linux 's mistakes. When you open a socket, you must use the following code segment at the same time.

Use the setsockopt () function:

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (Sockfd, Sol_Socket, SO_REUSEADDR, & OPT

& len;

#ENDIF

Only when you want to make the program not only in the Linux system, # ifdef and #endif description is required. Some U

The NIX system may not support or do not require a SO_REUSEADDR flag.

CONNECT () system call

CONNECT () calls when the client is connected to the server connected to the server, which is used .Connect () call must be

After use in bind (). It is defined as:

#include

#include

Int Connect (int Sockfd, Struct SockAddr * Servs

Addr, Int Addrlen

All parameters except the servsaddr are the same as the BIND call, servsaddr points to the server connected by the client.

Information. After receiving the request, Accept calls to create a new socket for the server. Then the server can () one

A new process and then wait for another connection. You can write code as the server is displayed in the program list 59.1.

Program List 59.1

Server-facing-socket protocol

#include

#include

#include

#include

#define my_port 6545

Main (int Argc, char * argv [])

{

Int sockfd, newfd;

INT CPID; / * Child ID * /

Struct SockAddr_in servaddr;

Struct SockAddr_in ClientInfo;

IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) <0)

{

Myabort ("Unable to create socket);

}

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

Bzero ((Char *) & Servaddr, Sizeof (Servaddr));

servaddr.sin_family = af_INet;

Servaddr.sin_addr.s_addr = HTONL (INADDR_Any);

servaddr.sin_family = htons (my_port);

/ *

* The HTONL (for a long integer) and htons (for short integer) Convert

* a host oriented byte Order * INTO A Network ORDER.

* /

IF (Bind (STRUCKFD, Struct Sockaddr *) & Servaddr, Sizeof (Struct SockAddr)) <0)

{

Myabort ("Unable to Bind Socket");

}

Listen (SockFD, 5);

For (;;)

{

/ * Wait here * / newfd = accept (Sockfd, (Struct SockAddr *) & ClientInfo,

SIZEOF (STRUCT SOCKADDR);

IF (newfd <0)

{

Myabort ("Unable to Accept on Socket);

}

IF ((CPID = fork ()) <0)

{

Myabort ("Unable to fork On Accept");

}

Else IF (cpid == 0) {/ * child * /

Close (sockfd); / * no need for Original * /

DO_YOUR_THING (Newfd);

exit (0);

}

Close (newfd); / * in the parent * /

}

In the program for the connection-oriented protocol, the server performs the following function:

Call the socket () function Create a socket.

Call the bind () function to bind himself on an address

Call listen () function listening connection

Call the accept () function Accept all the introduced requests

Call the read () function to get the introduced information and then call Write () to answer

Now let's take a look at the things you have to do, see the program list 59.2.

Program List 59.2

Client function

#include

#include

#include

#include

#define my_port 6545

#define my_host_addr "204.25.13.1"

Int getServersocketID ()

{

Int fd, len;

Struct SockAddr_in unix_addr;

/ * CREATE a Unix Domain Stream Socket * /

IF ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) <0)

{

Return (-1);

}

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

/ * Fill Socket Address StructureW / Our Address * /

MEMSET (& UNIX_ADDR, 0, SIZEOF (UNIX_ADDR));

UNIX_ADDR.SIN_FAMILY = AF_INET;

/ * Convert Internet Address to Binary Value * /

Unix_addr.sin_addr.s_addr = inet_addr (My_HOST_ADDR);

Unix_addr.sin_family = htons (my_port);

IF (Bind (Struct SockAddr *) & Unix_addr, len) <0)

Return (-2);

MEMSET (& UNIX_ADDR, 0, SIZEOF (UNIX_ADDR));

IF (Connect (FD, (Struct SockAddr *) & Unix_addr, len) <0)

Return (-3);

Return (FD);

}

In the connection-oriented communication, the client should do some things:

Call the socket () function Create a socket

Call the connect () function attempt to connect the server

If the connection successfully calls the Write () function request data, call the read () function to receive the incoming response

Not connected (ConnectionLESS) socket program design Now let us consider unconnected information exchange. The principle of its server and the connection-oriented protocol are not

Same. The server does not call Listen and Accept but call RecVFrom (). Similarly, the server uses the sendto () function.

Response information. Server-side program selection program list 59.3.

Program List 59.3

Service-Terminal

#include

#include

#include

#include

#define my_port 6545

#define maxm 4096

Char MESG [MAXM];

Main (int Argc, char * argv [])

{

Int sockfd, newfd;

INT CPID; / * Child ID * /

Struct SockAddr_in servaddr;

Struct SockAddr_in ClientInfo;

IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) <0)

{

Myabort ("Unable to create socket);

}

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

Bzero ((Char *) & Servaddr, Sizeof (Servaddr));

servaddr.sin_family = af_INet;

Servaddr.sin_addr.s_addr = HTONL (INADDR_Any);

servaddr.sin_family = htons (my_port);

/ *

* The HTONL (for a long integer) and htons (for short integer) Convert

* a host oriented byte Order * INTO A Network ORDER.

* /

IF (Bind (STRUCKFD, Struct Sockaddr *) & Servaddr, Sizeof (Struct SockAddr)) <0)

{

Myabort ("Unable to Bind Socket");

}

For (;;)

{

/ * Wait Here * /

n = Recvfrom (Sockfd, Mesg, Maxm, 0,

(Struct SockAddr *) & ClientInfo,

SIZEOF (STRUCT SOCKADDR);

DOSMETHINGTOIT (MESG);

Sendto (Sockfd, Mesg, N, 0,

(Struct SockAddr *) & ClientInfo,

SIZEOF (STRUCT SOCKADDR);

}

}

See it, handle each message only calls two functions, which is easier than the connection-oriented protocol. But you must, no matter

How to handle each message at the same time, because the message comes from multiple clients to the server.

In the discussion, the child process always knows where each message is coming.

The client can also call the Connect () system call. But the client can call the sendto () function directly. Customer

The machine and the server are roughly the same. Just call sendto () before calling Recvfrom ():

#include

#include

Int Sendto (Int Sockfd,

Const void * message__, / * the pointer to message * / int layth, / * of message * /

Unsigned int type, / * of routing, leave 0 * /

Const struct sockaddr * client, / * where to send it * /

INT Length); / * of sockaddr * /

Note: If you are using the BSD system, use the Sendto () system to call, do not use sendmsg (), because Send

To () performance is better.

If an error, -1 is returned, but the local error can only be checked.

Recvfrom () system call is defined in this:

#include

#include

Int Recvfrom (int Sockfd,

Const void * message__ / * the pointer to message * /

INT Length, / * of message * /

Unsigned int flags, / * of routing, leave 0 * /

Const struct sockaddr * client, / * where to send it * /

INT Length); / * of sockaddr * /

If an information is bigger buffer, then the additional information will be cut off. This call can be returned immediately, or

Waiting for a permanent. This depends on what type you set to Flags. You can even set up timeout (Timeout).

More information of RecVFrom can be found in MAN Pages.

Here you have learned how to use the performance of Linux's performance to design the basic knowledge of network applications. We don't fight

The more complex network programming is further described again. A excellent starting point for more details information is reference W. RIC

Hard Stevens << UNIX Network Program Design >> (Prentice Hall, 1990). This book is used by many universities.

The classic textbook, the content is extremely detailed.

Record and file lock

When two processes share a file, there is a very dangerous thing. If a process changed the file

The directory will inevitably affect another process. Based on this reason, most operating systems use a mutually exclusive principle (MUTUALLY)

Exclusive PrinciPle: When a process has a file, other processes can no longer touch this file. This is called

The file is locked.

This technology is very easy to implement. Usually what happens is that the so-called "locked file" is to create one and source file name

The name of the file plus the .lock extension. This tells other processes that this file can no longer touch. Linux spiper printing

Union and uucp is to achieve file lock. This may be a rude approach, but it is very simple to program.

Unfortunately, this technology is not practical when there are several processes to handle the same information at the same time. Because

Waiting for the file to open and close the delay will become very long. The same process is not correctly released, others

The process will hang there from going to get access rights.

For this reason, it is usually used to use record locks. Use records to lock, a small part of a large file is locked to prevent two

A process simultaneously changes it. If necessary, the record lock can make multiple processes simultaneously access different departments of the same file.

Divide a record. Of course, the record lock programming is more complicated than the implementation file.

Typically, to implement the record lock you need to use the file offset or the number of characters to the beginning of the file. In most programs

Among the characters within a range are locked. The program records the start and length of the lock range and saves in other processes.

Where is it. Whether it is writing a file lock or a record lock requires a good understanding of the operating system. But it is not difficult.

In particular, you can easily get thousands of procedures from Internet, Network Program Guide and BBS. You can see

The source code of these programs.

Inter-process communication

Network programming typically includes two or more processes to talk to each other (InterProcess Communications)

The process of process communication is extremely important in network programming. The network program design is not in some important aspects.

The method is usually used with general procedures. A traditional program can be dialogue through global variables or function calls and different modules (even other applications on the same machine). But not on the network.

An important goal of the network program design is to ensure that the process does not interfere. Otherwise, the system may be suspended or self-locking.

Therefore, there must be a simple and effective way to communicate between the processes. In this regard, UNIX has very significant robustness.

Many of the basic properties of UNIX are ideal for networks, queues, etc.

Compared with a single application code, the code between the process is more complicated. If you want to write such a program, you can

Learn the example of the online programming instructions and the examples on the BBS site. To understand these tasks?

summary

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 lot

The example program is the best way to start writing network code. But you have to spend many years.

--------------------------------------------------- ---------------

- 59 -

NetWork Programming

Ports and sockets

Socket programing

The socket () System Call

The bind () System Call

The listen () System Call

The accountpt () System Call

The setsockopt () and getsockopt () System calls

The connection () System Call

Listing 59.1. The Server Side for A Socket-Oriented Protocol.

Listing 59.2. The Client Side Function.

ConnectionLess Socket Programming

Listing 59.3. The Server Side.

Note

Record and file locking

Interprocess Communications

Summary

- 59 -

NetWork Programming

By Kamran Husain and Tim Parker

In this chapter

Ports and sockets

Socket programing

Record and file locking

Interprocess Communications

This Chapter Looks At The Basic Concepts You NEED For Network Programming:

Ports and sockets

Record and file locking

Interprocess Communications

IT Is Impossible to Tell You How To Program Applications for a Network in Just A

Few Pages. Indeed, The Best Available Reference To NetWork Programming Takes

Almost 800 Pages in The First Volume Alone! if you real want to do network

Programming, You NEED A LOT OF EXPERIENCE WITH Compilers, TCP / IP, And NetWork

Operating systems - and you need a great deal of patience.

For Details on TCP / IP, Check The Book Teach Yourself TCP / IP in 14 Days, by Tim

Parker (SAMS Publishing).

Ports and sockets

NetWork Programming Relies on The Use of Sockets To Accept and Transmitinformation. Although Thee Is A Lot of MyStique About Sockets, The Concept IS

Actually Simple to Understand.

Most Applications That Use the Two Primary Network Protocols, Transmission

Control Protocol (TCP) and User DataGram Protocol (UDP) Have a port number That

Identifies the Application. A Port Number IS Used for Each Different Application

The Machine IS Handling, So It Can Keep Track of Those Applications by Numbers

Rather Than Names. The Port Number Makes It Easier for the Operating System To

Know How Many Applications Are Using The System and Which Services Are

Available.

In Theory, Port Numbers Can Be Assigned On Individual Machines by The System

Administrator, But Some Conventions Have Been Adopted to Allow Better

Communications. Thase Conventions Enable The Port Number To Identify The Type of

Service That One System Is Requesting from Another. for this Reason, MOST

Systems maintain a file of port numbers and their corresponding services.

Port Numbers Are Assigned Starting from The Number 1. Normal, Port Numbers

Above 255 Are Reserved for The Private Use of the local machine, but number

Between 1 and 255 Are Used for Processes Requester by Remote Applications or for

Networking service.

Each Network Communications Circuit Into and Out of The Host Computer's TCP

Application Layer Is Uniquely Identified by a Combination of Two Numbers,

TOGETHER CALLED The Socket. The socket is composed of the ip address of the

Machine and the port number buy by the tcp software.

Because at Least Two Machines Are Involved in Network Communications, There Will

Be a socket on Both the sending and the receiving machine. Because the ip

Address of Each Machine Is Unique and The Port Numbers Are Unique To EACH

Machine, Socket Numbers Are Also Unique Across The Network. this setup enables

Another Application Across The Network Based Entirely

On the socket number.

The sending and receiving Machines Maintain A Port Table That Lists All Active

Port Numbers. The Two Machines Involved Have Reverse Entries for Each Session

Between The Two, A Process Called Binding. in Other Words, IF One Machine HAS

The Source Port Number 23 and The Destination Port Number Set at 25, The Other

Machine Has ITS Source Port Number Set At 25 and The Destination Port Number Set

AT 23.

Socket programing

Linux Supports BSD-Style Socket Programming. Both connection-orient and

ConnectionLESS TYPES of Sockets AresuTed. in Connection-Oriented

Communication, The Server and Client Establish A Connection Before Any Data IS

Exchanged. in ConnectionLess Communication, Data IS Exchanged As Part of A

Message. in Either Case, The Server Always Starts First, Binds Itself to a

Socket, And Listens to Messages. How The Server Attempts To Listen Depends on

The Type of Connection for Which you have programmed it.

You NEED TO KNOW ABOUT A FEW SYSTEM CALLS:

Socket ()

Bind ()

Listen ()

accept ()

Setsockopt () and getsockopt ()

Connect ()

Sendto ()

Recvfrom ()

WE Will Cover The System Calls in The Following Examples.

The socket () System Call

The socket () system call creates a socket for the client or the server. The

Socket Function Is Defined As Shown Here:

#include

#include

Int Socket (Int Family, Int Type, Int Protocol)

For Linux, You Will Have Family = AF_UNIX. The Type IS Either Sock_Stream for

Reliable, Though Slower, Communications or Sock_DGram for Faster, But Lessreliable, Communications. The Protocol Should Be ipproto_tcp for Sock_Stream and

Ipproto_udp for sock_dgram.

The Return Value from this function is -1 if there is an error; OtherWise, IT's

A Socket Descriptor. You will use this socket descriptor to refer to this socket

In all subssequent calls in your program.

Sockets are created a name. Clients Use the name of the socket to read

OR WRITE to It. This is where the bind function comes in.

The bind () System Call

The bind () system call assigns a name to an unnamed socket. The bind function is

Defined Like this:

#include

#include

INT Bind (int Sockfd, Struct SockAddr * Saddr, Int Addrlen)

THE FIRST ITEM IS A Socket Descriptor. The Second Is A Structure with The Name

To use, and the third item is the size of the structure.

Now That You have bound an address for your server or client, you can connect ()

To it or listen on it. if Your Program Is A Server, IT Sets Itself Up to Listen

And Accept Connections. Let's Look At The Function Available for Such An

Endeavor.

The listen () System Call

The listen () system call is buy by the server. It is defined in the following

Way:

#include

#include

INT Listen (int Sockfd, int backlog);

The sockfd is The descriptor of the socket. The backlog is the number of

Connections That Are Pending At One Time Before Any Are Rejected. Use T

Standard Value of 5 for Backlog. A Returned Value of Less Than 1 Idicates An

Error.

IF this Call Is Successful, You CAN Accept Connections.

The accountpt () System Call

THE ASTEM CALL IS Used by a Server to Accept Any Incoming Messages From Clients' Connect () Calls. Be aware That Function Does Not Return if NO

Connections Are Received. It is defined like this:

#include

#include

INT Accept (int Sockfd, Struct SockAddr * Peeraddr, Int Addrlen)

The Parameters Are The Same As Those for the Bind Call, with the Exception That

The Peeraddr Points To Information About The Client That Is Making A Connection

Request. based on the incoming message, The Fields in The Structure Pointed At

By Peeraddr Are Filled Out.

The setsockopt () and getsockopt () System calls

The Socket Libraries Provided with Linux Include A bug. The symptom of this bug

Is That You Cannot Reuse A Port Number for A Socket Even if you closed the

Socket Properly. for Example, Say You Write Your OWN Server That Waits on A

Socket. This Server Opens the socket and listens on it with no problem.

HOWEVER, FOR Some Reason (a crash or Normal Termination), WHEN THE PROGRAM IS

Restarted, you are not able to bind to the same port. The error cots from the

Bind () Call Will ALWAYS RETURN An Error Indicating That The Port you are

Attempting to connect to is already bound to another process.

THE PROBLEM IS THAT THE Linux Kernel Never Marks The Port as unused when

Process Bound to a socket Terminates. in Most Other UNIX Systems, The Port Can

BE USED Again by Another Invocation of The Same or EVEN ANOTHER Process.

THE WAY TO GET AROND This Problem in Linux is to use the setsockopt () system

Call to set the options on a socket when it is opened and before a connection is

Made on it. The setsockopt () sets options and the getsockopt () CALL GETS OPTIONS

For a given socket.here is the syntax for these calls:

#include

#include

INT GetSockopt (int Sockfd, int Level, int name, char * value, int * optlen)

Int setsockopt (int sockfd, int level, int name, char * value, int * optlen)

The Sockfd Must Be An Open Socket. The Level Is The Protocol Level To Use for

The function (ipproto_tcp for tcp / ip and sol_socket for socket level options),

And the name of the option is as defined in the socket's man page. The * Value

Pointer Points to a location where a value is stored for getsockopt () or WHEN A

Value is read for setsockopt (). The optlen parameter is a pointer to an integer

Containing the length of the parameters in bytes; the value is set by

Getsockopt () and must be set by the programmer when making a call VIA

Setsockopt ().

The Full Man Page with detils of all the options is found in the man page

Setsockopt (2).

Now Back to the bug in linux. When you Open a socket, you must also call the

Setsockopt () Function with the Following Segment of Code:

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

The #ifdef and #ndif Statements Are Necessary Only If You Want To Port The Code

Over to systems other Than Linux. Some Unix Systems Might Not Support or Require

The So_reuseAddr flag.

The connection () System Call

The connect () System call is buy by client in a

Connection-Oriented System. this connection () Call shop be name after the bind ()

Call. it is defined like this:

#include

#include

Int Connect (int SockFD, Struct SockAddr * Servsaddr, Int Addrlen)

The Parameters Are The Same As Those for the Bind Call, with the Exception Thatthe Servsaddr Points To Information About The Server That The Client IS

Connecting to. The Accept Call Creates A New Socket for the Server To Work with

The Request. This Way, The Server Can fork () OFF A New Process and Wait for more

Connections. on The Server Side of Things, You Would Have Code That Looks Like

That Shown in Listing 59.1.

Listing 59.1. The Server Side for A Socket-Oriented Protocol.

#include

#include

#include

#include

#define my_port 6545

Main (int Argc, char * argv [])

{

Int sockfd, newfd;

INT CPID; / * Child ID * /

Struct SockAddr_in servaddr;

Struct SockAddr_in ClientInfo;

IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) <0)

{

Myabort ("Unable to create socket);

}

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

Bzero ((Char *) & Servaddr, Sizeof (Servaddr));

servaddr.sin_family = af_INet;

Servaddr.sin_addr.s_addr = HTONL (INADDR_Any);

servaddr.sin_family = htons (my_port);

/ *

* The HTONL (for a long integer) and htons (for short integer) Convert

* a host oriented byte Order * INTO A Network ORDER.

* /

IF (Bind (STRUCKFD, Struct Sockaddr *) & Servaddr, Sizeof (Struct SockAddr)) <0)

{

Myabort ("Unable to Bind Socket");

}

Listen (SockFD, 5);

For (;;)

{

/ * Wait Here * /

Newfd = accept (Sockfd, (Struct SockAddr *) & ClientInfo,

SIZEOF (STRUCT SOCKADDR);

IF (newfd <0)

{

Myabort ("Unable to Accept on Socket);

}

IF ((CPID = fork ()) <0)

{

Myabort ("Unable to fork On Accept");

}

Else if (cpid == 0) {/ * child * / close (sockfd); / * no need for original * /

DO_YOUR_THING (Newfd);

exit (0);

}

Close (newfd); / * in the parent * /

}

}

In The Case of Connection-Oriented Protocols, The Server Performs The Following

Functions:

Creates A Socket with a call to the socket () Function

Binds itself to an address with the bind () Function Call

Listens for Connections with the listen () Function CALL

Accepts any incoming requests with the accept () Function CALL

Gets incoming messages with the read () function and replies with the write ()

Call

Now Let's Look At The Client Side of Things, IN LISTING 59.2.

Listing 59.2. The Client Side Function.

#include

#include

#include

#include

#define my_port 6545

#define my_host_addr "204.25.13.1"

Int getServersocketID ()

{

Int fd, len;

Struct SockAddr_in unix_addr;

/ * CREATE a Unix Domain Stream Socket * /

IF ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) <0)

{

Return (-1);

}

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

/ * Fill Socket Address Structure W / Our Address * /

MEMSET (& UNIX_ADDR, 0, SIZEOF (UNIX_ADDR));

UNIX_ADDR.SIN_FAMILY = AF_INET;

/ * Convert Internet Address to Binary Value * /

Unix_addr.sin_addr.s_addr = inet_addr (My_HOST_ADDR);

Unix_addr.sin_family = htons (my_port);

IF (Bind (Struct SockAddr *) & Unix_addr, len) <0)

Return (-2);

MEMSET (& UNIX_ADDR, 0, SIZEOF (UNIX_ADDR));

IF (Connect (FD, (Struct SockAddr *) & Unix_addr, len) <0)

Return (-3);

Return (FD);

}

The Client for Connection-Oriented Communication Also Takes The Following Steps: Creates A Socket with a call to the socket () Function

Attempts to Connect To The Server with a connection () CALL

IF a connection is name, requests data with the write () call, and reads

incoming replies with the read () function

ConnectionLess Socket Programming

Now Let's Consider The Case of a ConnectionLESS Exchange of Information. The

Principle on the server side is difference from the connection-oriented server

Side in That The Server Calls Recvfrom () Rather Than The Listen and Accept

....................

See Listing 59.3 for the Server Side.

Listing 59.3. The Server Side.

#include

#include

#include

#include

#define my_port 6545

#define maxm 4096

Char MESG [MAXM];

Main (int Argc, char * argv [])

{

Int sockfd, newfd;

INT CPID; / * Child ID * /

Struct SockAddr_in servaddr;

Struct SockAddr_in ClientInfo;

IF ((SockFD = Socket (AF_INET, SOCK_STREAM, 0) <0)

{

Myabort ("Unable to create socket);

}

#ifdef linux

OPT = 1; len = sizeof (opt);

Setsockopt (SOCKFD, SOL_SOCKET, SO_REUSEADDR, & OPT, & LEN);

#ENDIF

Bzero ((Char *) & Servaddr, Sizeof (Servaddr));

servaddr.sin_family = af_INet;

Servaddr.sin_addr.s_addr = HTONL (INADDR_Any);

servaddr.sin_family = htons (my_port);

/ *

* The HTONL (for a long integer) and htons (for short integer) Convert

* a host oriented byte Order * INTO A Network ORDER.

* /

IF (Bind (STRUCKFD, Struct Sockaddr *) & Servaddr, Sizeof (Struct SockAddr)) <0)

{

Myabort ("Unable to Bind Socket");

}

For (;;)

{

/ * Wait here * / n = recvfrom (sockfd, muesg, maxm, 0,

(Struct SockAddr *) & ClientInfo,

SIZEOF (STRUCT SOCKADDR);

DOSMETHINGTOIT (MESG);

Sendto (Sockfd, Mesg, N, 0,

(Struct SockAddr *) & ClientInfo,

SIZEOF (STRUCT SOCKADDR);

}

}

As you can see, The Two Function Calls to Process Each Message Make this an

Easier Implementation Than Connection-Oriented One. You Must, However, Process

Each Message One At a Time Because Messages from Multiple Clients Can Be

Multiplexed together. in a connection-oriented scheme, the child process always

Knows where each message originated.

The Client Does Not Have To Call The Connect () System Call Either. Instead, The

Client Can Call The Sendto () Function Directly. The Client Side Is Identical To

The Server Side, with The Exception That The sendto call is Made Before The SENDTO CALER I

Recvfrom () Call:

#include

#include

Int Sendto (Int Sockfd,

Const void * message__ / * the pointer to message * /

INT Length, / * of message * /

Unsigned int type, / * of routing, leave 0 * /

Const struct sockaddr * client, / * where to send it * /

INT Length); / * of sockaddr * /

NOTE: IF You Are A BSD User, Use the sendto () Call, NOT The sendmsg () Call.

The sendto () Call is more effect.

Any Errors Are Indicated By A Return Value of -1. Only Local Errors Are

Detected.

The recvfrom () System Call is defined as shown here:

#include

#include

Int Recvfrom (int Sockfd,

Const void * message__ / * the pointer to message * /

INT Length, / * of message * /

Unsigned int flags, / * of routing, leave 0 * /

Const struct sockaddr * client, / * where to send it * /

INT Length); / * of sockaddr * /

IF a message is too long to fit in the support buffer

Type of the flag being set. You can Even set timeout value. Check the man pages

For recvfrom for more information.

There you have it - the Very Basics of How To Program Applications to Take

Advantage of The Networking Capabilities Under Linux. We have not even scratched

The Surface of All The Intricacies of Programming for Networks. a good starting

Point for more detailed information would be unix network programming, by W

Richard Stevens (Prentice Hall, 1990). This book, a classic, is buy in MOST

Universities and is by far the maxild book to date.

Record and file locking

When Two Processes Want to Share A File, The Danger EXISTS THAT That ONE PROCESS

Might Affect The Contents of the File, And Thereby Affect The Other Process. for

This Reason, MOST OPERATING SYSTEMS USE A MUTUALLY Exclusive Principle: When ONE

Process Has A File Open, No Other Process Can Touch It. This Is Called File

LOCKING.

THIS TECHNIQUE IS Simple To Implement. What Usually Happens Is That A "LOCK

File "is created with the Same name as the Original File But with the extension

.lock, Which Tells Other Processes That The File IS Unavailable. this is how

Many Linux Spooles, Such As The Print System and uucp, import file locking.

IT IS A Brute-Force Method, Perhaps, But Effective and Easy To Program.

Unfortunately, this Technique Is Not Good When You Must Have SEVERAL Processes

Access The Same Information Quickly, Because The Delays Waiting for File Opening

And Closing Can Grow To Be Appreciable. Also, IF One Process Doesn't Release The

File Properly, Other Processes CAN HANG THERE, WAITI for Access.for This Reason, Record Locking IS Sometimes Implement. with Record Locking, A

Single Part of A Larger File Is Locked to Prevent Two Processes from Changing

ITS Contents At the Same Time. Record Locking Enables Many Processes To Access

The Same File At The Same Time, Each Updating Different Records within the file,

If Necessary. The Programming Necessary TO IMPLEMENT RECORD LOCKING IS MORE

Complex Than That for File Locking, of Course.

Normally, To Implement Record Locking, You Use A File Offset, or The Number of

Characters from the beginning of the file. in Most Cases, a Range of Characters

Is Locked; The Program Has To Note The Start of The Locking Region and the

Length of it, and then, and then, ingte information where other processes can Examine

IT.

Writing Either file-locking or record-locking code request a good understanding

Of the Operating System But IS OtherWise Not Difficult, Especially Because

THOUSANDS OF Programs Are Readily Available from The Internet, in Networking

Programming books, and on bbss to example for sample code.

Interprocess Communications

NetWork Programming Always Involves Two or More Processes Talking to Each Other

(InterProcess Communications), SO The Way In Which Processes Communicate IS

Vitally Important to NetWork Programmers. NetWork Programming Differs from THE

Usual Method of Programming in a Few Important Aspects. A Traditional Program

Can Talk to Different Modules (or Even Other Applications on The Same Machine)

THROUGH GLOBAL VARIABLES AND FUNCTION Calls. That Doesn't Work Across Networks.

A KEY GoAL of NetWork Programming Is To Ensure That Processes Don't Interfere

WITH EACH Other. OtherWise, Systems Can Get Bogged Down or CAN Lock Up.ThereFore, Processes Must Have a Clean and Efficient Method of Communicating.

UNIX IS Particularly Strong in this Regard, Because Many of the Basic UNIX

Capabilities, Such as pipes and queues, Are Used Effectively Across Networks.

Writing code for Interprocess Communications IS Quite Difficult Compared To

SINGLE Application Coding. If You Want To Write this Type of Routine, you Should

Study Sample Programs from A NetWork Programming Book or A Bbs Site To See How How

THIS TASK IS Accomplished.

Summary

Few People Need to Write Network Applications, So The Details of the Process Are

Best Left to Those Who Want Them. Experience and Lots of Examples Are The Best

Way to Begin Writing Network Code, And Mastering The Skills Can Take Many Years.

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

New Post(0)