Linux network programming, Part 1: BSD socket (below)

zhaozj2021-02-16  83

(Attached to the upper article) 2. Establish a corresponding client as you are seeing, compared to the server, the client's code is simple. In this program you have to provide two command line parameters: the server hosting the machine host name or IP address, and the port bound to the service segment. Of course, the server must also operate normally before the client is running: p.

/ * Listing 2: * An Example Client for "Hello, World!" Server * Ivan Griffin (Ivan.griffin@ul.ie) * /

/ * Hellwolf MISTY TRANSLATED * /

#include / * perror () * / # include / * atoi () * / # include #include #include / * read () * / # include #include #include

int main (int argc, char * argv []) {int clientSocket, remotePort, status = 0; struct hostent * hostPtr = NULL; struct sockaddr_in serverName = {0}; char buffer [256] = ""; char * remoteHost = NULL;

IF (3! = argc) {fprintf (stderr, "usage:% s / n", argv [0]); exit (1);}

Remotehost = argv [1]; Remoteport = ATOI (Argv [2]);

ClientSocket = Socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == Clientsocket) {Perror ("socket ()"); exit (1);}

/ * * First, it is assumed to be DNS hostname * Note: * struct hostent {* char * h_name; / * official name of host * / * char ** h_aliases; / * alias list * / * int h_addRType; / * Host Address Type * / * Int h_length; / * length of address * / * char ** h_addr_list; / * list of addresses from name server * / *}; * #define h_addr h_addr_list [0] * noticed? H_addr is a macro, if you use GDB debugging * Display phostent-> h_addr error, do not strange * / hostptr = gethostByname (transotehost); / * struct hostent * hostptr; * / if (null == hostptr) {/ * is not ? ? * / Hostptr = gethostbyaddr (Remotehost, Strlen (Remotehost), AF_INET); / * It should be the IP address of the point-point * / if (null == hostptr) / * is not,! -_- * / {PERROR "Error resolving server address"); exit (1);}} serverName.sin_family = AF_INET; serverName.sin_port = htons (remotePort); (void) memcpy (& hostPtr- hostPtr- h_length serverName.sin_addr,> h_addr,>);

/ * Here you don't need to bind, because Connect can solve all * / status = connect (client socket, (struct socddr *) & servername, sizeof (servername)); if (-1 == status) {PERROR "Connect ()"); exit (1);} / * Connect successfully, a duplex network connection is established * like a server, the client can use read () and write () reception Data / * * The specific code of the client should begin to implement * such as from server acceptance and response information, etc. * / while (0 <(clientSocket, buffer, sizeof (buffer) - 1))) {printf ("% d:% s", status, buffer; / * Note: If the read is successful, Status represents the number of bytes (including '/ 0') * /}

IF (-1 == status) {perror ("read ()");} close (clientsocket);

Return 0;}

What do you need to pay attention to:

Send text is usually working properly. However, remember that different systems have different systems (for example, UNIX uses / 0x12, and Microsoft uses / 0x15 / 0x12).

Different implementations may use different byte order (byte-order). But don't worry, the BSD designers are considering this. There are many ready-made functions to achieve this conversion, they have a certain naming rule: HTons represents the conversion of Host-to-Network's Short structure, and HTONL, NTOHS, NTOHL, and it is also very easy to judge their way of work. . As for the network word sequence is a big-endian or little-endian, it is not a problem, because it has been standardized on the TCP / IP network (Note: Network byte is Big end alignment). Of course, unless you have been sending a character on the network (Note: Also ASCII), no need for these conversion functions, but usually, you will encounter a word order problem. This also looks at your machine, sometimes these functions are empty, sometimes they are really a function. Interestingly, the most common network programming BUGS source is forgot to use these functions when the SIN_ADDR.S_ADDR field fills the SockAddr_in structure, even if INADDR_ANY is used. An important goal of network programming is that it does not give both sides to bring unpredictable troubles. For example, the server must synchronize access to this part of the resource through the necessary mechanisms, avoiding the resulting deadlock and ensuring the effectiveness of the data. In most cases, you can't transfer pointers from the machine and try to use it. <> Similarly, in most cases, you can't try to pass a file descriptor from a process to another process (non-child process) through a set interface and use it directly. The BSD and SVR4 systems provide different methods for delivering a file descriptor between the unrelated processes; however, the easiest way to Linux is by using the / PROC file system. In addition, you have to ensure that you have solved the Short Writes issue correctly. Short Write occurs in Write () calls only partially write buffers to a device corresponding to a file descriptor. The reason they happen is attributed to the buffer of the operating system, and the stream control system of the underlying transmission system. Some system calls are often referred to as slow system calls may be interrupted by (other call). Some may not be restarted, so you must have a declare to solve this problem when programming. The following code solves the Short Write question: / * Listing 3: * Handling shortwrites * Ivan griffin (Ivan.griff@ul.ie) * // * hellwolf missy translated * / int Bytestosnd = 0, byteswritten = 0, Num = 0; / * * Bytestosend, Buffer, and * fileDesc here, must already be defined in other places. * /

For (byteswritten = 0; byteswritten

IF (Num <0) {PERROR ("Write ()"); if (errno! = Eintr) {EXIT (1);}}}

Using multithreading rather than multi-process may alleviate the burden on the server, and more effective. The conversion of the context of the thread (of course means that the same process space) is usually smaller than the process between the processes. However, so many sub-threads are operating network I / O, if they are within the kernel level, but if they are user-level, the entire process is blocked because of the first call I / O thread. This will result in the hunger state of other threads who do not see to see until I / O completion. As you can see, when using a simple forking model, close unnecessary socket descriptors in the parent process and sub-process is quite ordinary. This protects the potential error of the process to read and write these descriptors. But don't try to do this when using a thread model, multi-threads in the process share the same memory virtual address space and file descriptor set. If you close a descriptor in a thread, all other threads in the process will not be able to obtain the descriptor.

3. Unconnected Data Transport - The code under theUDP shows a server that uses UDP. The UDP program is very similar to the TCP program, but they are very different. First, UDP does not guarantee reliable transmission - if you need reliability when you use UDP, you must or turn your own or turn to TCP. Like a TCP program, you can build a socket with UDP and bind it to a specific address. The UDP server does not listen (listen) and accepts external connections, customers do not have to explicitly connect to the server. In fact, there is not much difference between the UDP client and the service segment. The server must be bound to a determined port and address so that the client knows where to send data. And when your server uses Send (), the client should also use the corresponding RECV family. UDP server program list: / * Listing 4: * Example UDP (ConnectionLESS) Server * Ivan Griffin (Ivan.griffin@ul.ie) * /

#include #include #include #include #include #include #include #include #include

#define max_mesg_size 4096char MESG [MAX_MESG_SIZE] = ""

INT main (int Argc, char * argv []) {INT udpsocket = 0, myport = 0, status = 0, size = 0, clientLength = 0; struct sockaddr_in servername = {0}, clientname = {0};

IF (2! = argc) {fprintf (stderr, "usage:% s / n", argv [0]); exit (1);

Myport = ATOI (Argv [1]);

UDPSocket = Socket (PF_INET, SOCK_DGRAM, / * PF_INET, and SOCK_DGRAM combination represents udp * / ipproto_udp); if (-1 == udpsocket) {Perror ("socket ()"); exit (1);} Memset (& ServerName, 0, SIZEOF (ServerName)); MEMSET (& ClientName, 0, Sizeof (ClientName);

ServerName.sin_Family = AF_INET; ServerName.SIN_ADDR.S_ADDR = HTONL (INADDR_Addr_Anddr_ "; servername.sin_port = HTONS (MyPort);

Status = BIND (Udpsocket, (Struct SockAddr *) & ServerName, SIZEOF (ServerName)); if (-1 == status) {PERROR ("Bind ()"); exit (1);

For (;;) {/ * ssize_t recvfrom (int S, void * buf, size_t len, int flags, struct sock- * addr * from, socklen_t * fromlen); * / size = recvfrom (udpsocket, muesg, max_mesg_size, 0 (Strunt sockaddr *) & clientName, & ClientLength; if (size == -1) {Perror ("Recvfrom ()"); exit (1);} / * SSIZE_T Sendto (int S, const void * msg, size_t g , int flags, const * struct sockaddr * to, socklen_t tolen); * / status = sendto (udpSocket, mesg, size, 0, (struct sockaddr *) & clientName, clientLength);! if (status = size) {fprintf (stderr "Sendto (): short write./n"); exit (1);}}

/ * never reached * / return 0;}

Customizing the TCP client to a UDP client will be left as an exercise

4, / etc / service file In order to connect to a server, you must first know the address and port of its listening. Many common services (FTP, Telnet, etc.) are listed in a text article.

Parts / etc / services. GetServByname () function can use the name to ask a service detail included its port number (note! It is already a network word sequence), its prototype

/ usr / include: struct server * getServbyName (const char * name, const char * proto); Default Proto is "TCP"

Struct servent {char * s_name; / * official service name * / char ** s_aliases; / * alias list * / int s_port; / * port number, network * byte-order - so do not * use host-to-network Macros * / char * s_proto; / * protocol to use * /}; 5, summary This article describes the network programming using the C and BSD Socket API under Linux. In general, using this API to write code will be quite laborious, especially to others.

Compared with technology. In future articles, I will compare the BSD Socket API with the other two methods that can be selected: Remote Process Call (RPCS, Remote Procedure

Calls and CORBA (Common Object Request Broker Achitecture, public object requesting agent [scheduling) program architecture). RPCS in Ed Petron's article "Remote

Procedure Calls "(Linux Journal Issue # 42, October 1997) is introduced.

Related resources: UNIX Network Programming, W. Richard Steves, Prentice Hall, 1990.

An Introductory 4.4BSD Interprocess Communication Tutorial, Stuart Sechrest, University of California, Berkeley. 1986.

Available Via Anonymous FTP At: ftp://ftp.netbsd.org/pub/netbsd/misc/lite2-docs/psd/20.ipctut.ps.gz.

An Advanced 4.4bsd Interprocess Communication Tutorial, Samuel J. Leffler, Robert S. Fabry, William N. Joy, Phil Lapsley,

University of California, Berkeley. 1986 Available Via Anonymous ftp at: ftp://ftp.netbsd.org/pub/netbsd/misc/lite2-

DOCS / PSD / 21.IPC.ps.gz.

Java and The Client-Server, Joe Novosel, Linux Journal, Issue 33, January 1997.

RFC 793: Transmission Control Protocol, J. Postel (ed.), September 1981. Available Via HTTP AT

Http://www.internic.net/rfc/rfc793.txt.

RFC 1337: Time-Wait Assassination Hazards in TCP, R. Braden, May 1992. Available Via HTTP AT

Http://www.internic.net/rfc/rfc1337.txt.

Programming Unix Sockets In C FAQ, Vic Metcalfe, Andrew Gierth and Other Contributers, February 1997. Available Via HTTP AT

http://kipper.york.ac.uk/~vic/sock-faq/html/unix-socket-faq.html

About the author: Ivan Griffin is a research postgraduate student in the ECE department at the University of Limerick, Ireland His interestsinclude C / Java, WWW, ATM, the UL Computer Society (http://www.csn.ul.ie/). And, of course, linux

(http://www.trc.ul.ie/~griffini/linux.html). His E-mail address is ivan.griffin@ul.ie.

Dr. John Nelson IS A Senior Lecturer In Computer Engineering At the University of Limerick. HIS Interests include Mobile Mobile. His Interests Include Mobile

Communications, Intelligent NetWorks, Software Engineering and Vlsi Design. His E-mail Address is john.nelson@ul.ie.

All programs can be obtained here: ftp://ftp.ssc.com/pub/lj/listings/issue46/2333.tgz

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

New Post(0)