Linux interprocess communication Mode--local Socket__linux

Source: Internet
Author: User
Tags strlen

Previous Code First

Service side:

s_unix.c #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h
    > #define UNIX_DOMAIN "/tmp/unix.domain" int main (void) {socklen_t clt_addr_len;
    int listen_fd;
    int com_fd;
    int ret;
    int i; 
    static Char recv_buf[1024];
    int Len;
    struct Sockaddr_un clt_addr;
    struct Sockaddr_un srv_addr;
    Listen_fd=socket (pf_unix,sock_stream,0);
        if (listen_fd<0) {perror ("Cannot create communication socket");
    return 1;
    }//set server Addr_param Srv_addr.sun_family=af_unix;
    strncpy (srv_addr.sun_path,unix_domain,sizeof (Srv_addr.sun_path)-1);
    Unlink (Unix_domain);
    Bind SOCKFD & Addr Ret=bind (listen_fd, struct sockaddr*) &srv_addr,sizeof (SRV_ADDR));
        if (ret==-1) {perror ("Cannot bind server socket");
        Close (LISTEN_FD);
        Unlink (Unix_domain);
    return 1;
    }//listen sockfd Ret=listen (listen_fd,1); IfRet==-1) {perror ("Cannot listen the client connect request");
        Close (LISTEN_FD);
        Unlink (Unix_domain);
    return 1;
    //have Connect Request Use accept len=sizeof (CLT_ADDR);
    Com_fd=accept (LISTEN_FD, (struct sockaddr*) &clt_addr,&len);
        if (com_fd<0) {perror ("Cannot accept client connect request");
        Close (LISTEN_FD);
        Unlink (Unix_domain);
    return 1;
    //read and printf sent client info printf ("/n=====info=====/n");
        for (i=0;i<4;i++) {memset (recv_buf,0,1024);
        int Num=read (com_fd,recv_buf,sizeof (RECV_BUF));  
    printf ("Message from client (%d)):%s/n", num,recv_buf);
    Close (COM_FD);
    Close (LISTEN_FD);
    Unlink (Unix_domain);
return 0;
 }

Client:

//c_unix.c #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #
    Include <sys/un.h> #define UNIX_DOMAIN "/tmp/unix.domain" int main (void) {int connect_fd;
    int ret;
    Char snd_buf[1024];
    int i;
static struct Sockaddr_un srv_addr;
    creat UNIX Socket Connect_fd=socket (pf_unix,sock_stream,0);
        if (connect_fd<0) {perror ("Cannot create communication socket");
    return 1;
    } Srv_addr.sun_family=af_unix;
strcpy (Srv_addr.sun_path,unix_domain);
    Connect Server Ret=connect (connect_fd, struct sockaddr*) &srv_addr,sizeof (SRV_ADDR));
        if (ret==-1) {perror ("Cannot connect to the server");
        Close (CONNECT_FD);
    return 1;
    } memset (snd_buf,0,1024);
strcpy (SND_BUF, "Message from client");
    Send info Server for (i=0;i<4;i++) write (connect_fd,snd_buf,sizeof (SND_BUF));
    Close (CONNECT_FD);
return 0; }


In addition to the use of sockets to achieve communication between different hosts between the network, but also to achieve the same host of different processes between the communication, and the established communication is two-way communication. The socket process communicates with network communication using a uniform set of interfaces, except that the address structure differs from some parameters.

First, create the socket process

(1) Create a socket, type af_local or Af_unix, for process communication:

Creating a socket requires a socket system call with the following prototype:


int socket (int domain, int type, int protocol);


Where the domain parameter specifies the protocol family, for the local socket, the value must be set to the Af_unix enumeration value, the type parameter specifies the socket type, the protocol parameter specifies the specific protocol, and the type parameter can be formatted as SOCK_STREAM (streaming socket) or Sock_ Dgram (datagram socket), the Protocol field should be set to 0; its return value is the generated socket descriptor.


For local sockets, a streaming socket (SOCK_STREAM) is a sequential, reliable bidirectional byte stream, which is equivalent to creating a data channel between local processes; a datagram socket (SOCK_DGRAM) is equivalent to sending a message, and in process communication, In theory, there may be information lost, copied, or not in a sequential order, but because of its local communication, and not through the outside network, these situations appear to be very small probability.


Second, named socket.

Both sides of a sock_stream local socket need to have a local address, where the local address of the server side needs to be explicitly specified, and the method is to use a struct sockaddr_un type variable.

struct Sockaddr_un {
sa_family_t sun_family; * Af_unix * *
Char Sun_path[unix_path_max]; /* Path name * *
};

There's a key thing in this, there are two ways to name the socket process. One is the ordinary name, the socket will be based on this name to create a socket file with the same name, the client connection by reading the socket file to connect to the socket server. The disadvantage of this approach is that the server must have write access to the socket file path, the client must know the socket file path, and must have read access to the path.

Another way to name it is to abstract the namespace, which does not require the creation of a socket file, just name a global name and allow the client to connect according to that name. The latter realization process differs from the former in that the latter must place the first byte at 0, i.e. sun_path[0] = 0, when assigning values to the members of the address structure Sun_path, as shown in code:


The first way:

Name the server socket 
	server_addr.sun_family = Af_unix;
	strcpy (Server_addr.sun_path, "/tmp/unix.domain");
	Server_len = sizeof (struct sockaddr_un);
	Client_len = Server_len;



The second way:

#define SERVER_NAME @socket_server

Name the socket
    server_addr.sun_family = Af_unix;
    strcpy (Server_addr.sun_path, server_name);
    server_addr.sun_path[0]=0;
    Server_len = sizeof (SERVER_ADDR);
    Server_len = strlen (server_name)  + offsetof (struct sockaddr_un, sun_path);



Where the Offsetof function is defined in the #include <stddef.h> header file. Because the first byte of the second method is 0, we can add a placeholder string before the named string server_name, for example:
#define SERVER_NAME @socket_server  

The @ sign above represents a placeholder, not the actual name.

Hint: when the client connects to the server, it must be the same as the service end, that is, if the service side is a normal naming method, the address of the client must also be a normal naming method; If the service end is an abstract naming method, the address of the client must also be an abstract naming method.


Third, binding

Both parties to a sock_stream local socket need to have a local address, where the server-side local address needs to be explicitly specified by using a struct Sockaddr_un type of variable, assigning the corresponding field to a value, and then binding it to the server socket created, binding to use the Bind system call, whose prototype is as follows:


int bind (int socket, const struct SOCKADDR *address, size_t Address_len);


Where the socket represents a server-side socket descriptor that addresses the local address that needs to be bound, is a struct sockaddr_un type variable, address_len the byte length of the local address. The code that implements the server-side address-specific functionality is as follows (assuming that the server side has created a socket using the socket system call described above, SERVER_SOCKFD is its socket descriptor):
struct Sockaddr_un server_address;
server_address.sun_family = Af_unix;
strcpy (Server_address.sun_path, "Server Socket");
Bind (SERVER_SOCKFD, (struct sockaddr*) &server_address, sizeof (server_address));


The client's local address is not explicitly specified and can only be connected to the server side, therefore, the client's struct sockaddr_un type variable needs to be set according to the server settings, as follows (assuming that the client has created a socket through the socket system call described above, CLIENT_SOCKFD for its socket descriptor):
struct Sockaddr_un client_address;
client_address.sun_family = Af_unix;
strcpy (Client_address.sun_path, "Server Socket");

Iv. Monitoring
After server-side sockets are created and given a local address value (the name, in this case, the server Socket), you need to listen, wait for the client to connect and process the request, listen for the listen system call, accept the client connection using the Accept system call, and their prototype is as follows:
int listen (int socket, int backlog);
int accept (int socket, struct sockaddr *address, size_t *address_len);
Where the socket represents the server-side socket descriptor; Backlog indicates the length of the queued connection queue (if multiple clients are connected at the same time, a queue is required); address represents the local location of the current connection client, which is an output parameter and is the information that the client passes over itself ; Address_len represents the byte length of the current connection client's local address, which is both an input parameter and an output parameter. The code that implements listening, receiving, and processing is as follows:
#define Max_connection_number 10
int server_client_length, SERVER_CLIENT_SOCKFD;
struct Sockaddr_un server_client_address;
Listen (SERVER_SOCKFD, max_connection_number);
while (1)
{
// ...... (Some process code)
server_client_length = sizeof (server_client_address);
SERVER_CLIENT_SOCKFD = Accept (SERVER_SOCKFD, (struct sockaddr*) &server_client_address, &server_client_length);
// ...... (Some process code)
}
The reason for using the dead loop here is that the server is an ongoing service entity that requires uninterrupted listening, accepting, and processing connections, in this case, each connection can only be processed serially, that is, after a connection is processed, subsequent connections can be processed. If you want multiple connections to be processed concurrently, you need to create a thread and give each connection to the appropriate thread for concurrent processing.
Once the client socket has been created and given a local address value, it is necessary to connect to the server side for communication and to have the server provide processing services for it. For streaming sockets of type sock_stream, it is necessary for the client to connect to the server before it can be used. Connection to use Connect system call, its prototype


int connect (int socket, const struct SOCKADDR *address, size_t Address_len);


Where socket is the socket descriptor for the client, address represents the current client's local location, is a struct sockaddr_un type variable, and Address_len represents the byte length of the local address. The code to implement the connection is as follows:
Connect (CLIENT_SOCKFD, (struct sockaddr*) &client_address, sizeof (client_address));
Both the client and the server have to interact with each other on the data, and this interaction is the subject of our process communication. One process plays the role of the client, another process plays the role of the server, and two of processes send and receive data between each other, which is the process communication based on the local socket. Send and receive data using the write and read system calls, which are:
int read (int socket, char *buffer, size_t len);
int write (int socket, char *buffer, size_t len);
Where the socket is a socket descriptor; Len is the length of the data that needs to be sent or received; for the read system call, buffer is used to hold the receiving data, that is, the received data is stored in it, is an output parameter; For write system calls, buffer Used to store data that needs to be sent out, that is, the data in the buffer is sent out, is an input parameter, and the return value is the length of the data that has been sent or received. For example, if the client sends a "Hello" string to the server, the code is as follows:
Char buffer[10] = "Hello";
Write (client_sockfd, buffer, strlen (buffer));
After the interaction is complete, you need to disconnect the connection to save resources and use the close system call with the following prototype:
int close (int socket);
Not much said, direct use, we will certainly, hehe.
Each system call described above has a 1 return value, which returns 1 when the call is unsuccessful, which allows us to use IF-ELSE or exception handling statements to handle errors, providing great convenience for us.
There are few applications for SOCK_DGRAM datagram local sockets, because streaming sockets can be ignored for local connection times, so efficiency is not improved, and send and receive need to carry each other's local address, so few or even almost no use.
corresponding to a local socket is a network socket that can be used to transfer data over a network, in other words, to implement process communication processes on different machines. In the TCP/IP protocol, the first byte of an IP address is 127 that is local, so local socket traffic can be implemented using a network socket with an IP address of 127.x.x.x.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.