Linux本地套接字

LINUX和UNIX都拥有一个非常实用的工具--UNIX套接字,或称为本地套接字,它可以被用在进程间通讯(IPC)当中。UNIX套接字的运转机制和Internet套接字类似,主要的区别UNIX套接字只能用在一台计算机中,而Internet套接字则可以在不同的计算机之间使用。UNIX套接字定址的方式是作为本地文件系统里的一个文件。

你可能会奇怪为什么要使用UNIX套接字而不使用常规的Internet套接字呢?或许最大的原因就是安全和速度了。无论何时,当你打开任何Internet套接字的时候,你可能就帮远程的黑客打开了入侵之门。



创建
使用套接字函数socket创建,不过传递的参数与网络套接字不同。域参数应该是PF_LOCAL或者PF_UNIX,而不能用PF_INET之类。本地套接字的通讯类型应该是SOCK_STREAM或SOCK_DGRAM,协议为默认协议。例如:
 int sockfd;
 sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);

绑定
创建了套接字后,还必须进行绑定才能使用。不同于网络套接字的绑定,本地套接字的绑定的是struct sockaddr_un结构。struct sockaddr_un结构有两个参数:sun_family、sun_path。sun_family只能是AF_LOCAL或AF_UNIX,而sun_path是本地文件的路径。通常将文件放在/tmp目录下。例如:

 struct sockaddr_un sun;
 sun.sun_family = AF_LOCAL;
 strcpy(sun.sun_path, filepath);
 bind(sockfd, (struct sockaddr*)&sun, sizeof(sun));

监听
本地套接字的监听、接受连接操作与网络套接字类似。

连接
连接到一个正在监听的套接字之前,同样需要填充struct sockaddr_un结构,然后调用connect函数。

连接建立成功后,我们就可以像使用网络套接字一样进行发送和接受操作了。

服务器端代码


    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <sys/un.h>
    #include <unistd.h>
    #include <stdlib.h>

    int main (int argc, char *argv[])
    {
            int server_sockfd, client_sockfd;
            int server_len, client_len;
            struct sockaddr_un server_address;      /*声明一个UNIX域套接字结构*/
            struct sockaddr_un client_address;
            int i, bytes;
            char ch_send, ch_recv;

            unlink ("server_socket");       /*删除原有server_socket对象*/

            /*创建 socket, 通信协议为AF_UNIX, SCK_STREAM 数据方式*/
            server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0);

            /*配置服务器信息(通信协议)*/
            server_address.sun_family = AF_UNIX;

            /*配置服务器信息(socket 对象)*/
            strcpy (server_address.sun_path, "server_socket");

            /*配置服务器信息(服务器地址长度)*/
            server_len = sizeof (server_address);

            /*绑定 socket 对象*/
            bind (server_sockfd, (struct sockaddr *)&server_address, server_len);

            /*监听网络,队列数为5*/
            listen (server_sockfd, 5);

            printf ("Server is waiting for client connect...\n");

            client_len = sizeof (client_address);

            /*接受客户端请求; 第2个参数用来存储客户端地址; 第3个参数用来存储客户端地址的大小*/
            /*建立(返回)一个到客户端的文件描述符,用以对客户端的读写操作*/
            client_sockfd = accept (server_sockfd, (struct sockaddr *)&server_address, (socklen_t *)&client_len);
            if (client_sockfd == -1) {
                    perror ("accept");
                    exit (EXIT_FAILURE);
            }

            printf ("The server is waiting for client data...\n");

            for (i = 0, ch_send = '1'; i < 5; i++, ch_send++) {
                    if ((bytes = read (client_sockfd, &ch_recv, 1)) == -1) {
                            perror ("read");
                            exit (EXIT_FAILURE);
                    }

                    printf ("The character receiver from client is %c\n", ch_recv);

                    sleep (1);

                    if ((bytes = write (client_sockfd, &ch_send, 1)) == -1) {
                            perror ("read");
                            exit (EXIT_FAILURE);
                    }
            }

                    close (client_sockfd);
                    unlink ("server socket");
    }

客户端代码

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <sys/un.h>
    #include <unistd.h>
    #include <stdlib.h>

    int main (int argc, char *argv[])
    {
        struct sockaddr_un address;
        int sockfd;
        int len;
        int i, bytes;
        int result;
        char ch_recv, ch_send;

        /*创建socket,AF_UNIX通信协议,SOCK_STREAM数据方式*/
        if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                perror ("socket");
                exit (EXIT_FAILURE);
        }

        address.sun_family = AF_UNIX;
        strcpy (address.sun_path, "server_socket");
        len = sizeof (address);

        /*向服务器发送连接请求*/
        result = connect (sockfd, (struct sockaddr *)&address, len);
        if (result == -1) {
            printf ("ensure the server is up\n");
            perror ("connect");
            exit (EXIT_FAILURE);
        }

        for (i = 0, ch_send = 'A'; i < 5; i++, ch_send++) {
            if ((bytes = write(sockfd, &ch_send, 1)) == -1) { /*发消息给服务器*/
                perror ("write");
                exit (EXIT_FAILURE);
            }

            sleep (2);    /*休息二秒钟再发一次*/

            if ((bytes = read (sockfd, &ch_recv, 1)) == -1) { /*接收消息*/
                perror ("read");
                exit (EXIT_FAILURE);
            }

            printf ("receive from server data is %c\n", ch_recv);
        }
        close (sockfd);

        return (0);
    }

如果服务器和客户端依次运行,可以在两边看到输出:
服务器端
 ./sock_local_server
Server is waiting for client connect...
The server is waiting for client data...
The character receiver from client is A
The character receiver from client is B
The character receiver from client is C
The character receiver from client is D
The character receiver from client is E
客户端
./sock_local_client
receive from server data is 1
receive from server data is 2
receive from server data is 3
receive from server data is 4
receive from server data is 5

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
套接字(Socket)是一种通信机制,它允许不同的进程在同一主机或不同主机之间进行通信Linux下的套接字编程可以使用C语言的套接字接口库函数来实现。 以下是一个简单的Linux套接字编程教程: 1. 创建套接字 使用socket()函数创建一个套接字。socket()函数的原型如下: ```c int socket(int domain, int type, int protocol); ``` 其中,domain指定协议族,type指定套接字类型,protocol指定协议。常用的协议族有AF_INET(IPv4)和AF_INET6(IPv6),套接字类型有SOCK_STREAM(TCP)和SOCK_DGRAM(UDP),协议有IPPROTO_TCP和IPPROTO_UDP等。 例如,创建一个TCP协议的套接字: ```c int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ``` 2. 绑定地址 使用bind()函数将套接字与一个地址绑定。bind()函数的原型如下: ```c int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ``` 其中,sockfd是要绑定的套接字描述符,addr是一个指向地址结构体的指针,addrlen是地址结构体的长度。 例如,绑定到本地IP地址和指定端口号: ```c struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(8080); int ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); ``` 3. 监听连接 使用listen()函数将套接字设置为监听状态。listen()函数的原型如下: ```c int listen(int sockfd, int backlog); ``` 其中,sockfd是要监听的套接字描述符,backlog是在内核中排队等待的连接的最大数量。 例如,设置最大排队数量为5: ```c int ret = listen(sockfd, 5); ``` 4. 接受连接 使用accept()函数接受客户端连接请求,并创建一个新的套接字用于与客户端进行通信。accept()函数的原型如下: ```c int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ``` 其中,sockfd是监听套接字描述符,addr是一个指向地址结构体的指针,用于存储客户端的地址信息,addrlen是地址结构体的长度。 例如,接受客户端连接请求,并创建一个新的套接字描述符: ```c struct sockaddr_in client_addr; socklen_t client_addrlen = sizeof(client_addr); int newfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addrlen); ``` 5. 发送和接收数据 使用send()函数向对端发送数据,使用recv()函数从对端接收数据。send()和recv()函数的原型如下: ```c ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags); ``` 其中,sockfd是要发送或接收数据的套接字描述符,buf是要发送或接收的缓冲区,len是缓冲区的长度,flags是可选的标志参数。 例如,发送数据: ```c char msg[] = "Hello World!"; int ret = send(newfd, msg, sizeof(msg), 0); ``` 例如,接收数据: ```c char buf[1024]; int ret = recv(newfd, buf, sizeof(buf), 0); ``` 6. 关闭套接字 使用close()函数关闭套接字。close()函数的原型如下: ```c int close(int fd); ``` 其中,fd是要关闭的套接字描述符。 例如,关闭套接字: ```c close(sockfd); ``` 以上是一个简单的Linux套接字编程教程。套接字编程涉及到许多细节和复杂的操作,需要仔细学习和实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值