【编程】unix socket 学习的记录

1 gcc ser.c -o ser
#include 
#include 
#include 
#include 
#include 
#include 

#define UN_SOCK_PATH "/home/admin/zzk_tenda/unix_socket/server.socket"

int main(int argc, char *argv[])
{
    int sockfd, newfd, ret , recv_num, recv_num_total = 0;
    char buf[50];
    struct sockaddr_un server_addr;

    remove(UN_SOCK_PATH);
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strcpy(server_addr.sun_path, UN_SOCK_PATH);

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        perror("socket");
    }
    else
        printf("socket\n");

    ret = bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(server_addr));
    if (ret < 0)
    {
        perror("bind");
    }
    else
        printf("bind\n");

    ret = listen(sockfd, 4);
    if (ret < 0)
    {
        perror("listen");
    }
    else
        printf("listen\n");

    newfd = accept(sockfd, NULL, NULL);
    if (newfd < 0)
    {
        perror("accept");
    }
    else
    {
        printf("accept\n");
    }

    while(1)
    {
        recv_num = recv(newfd, buf, 24, 0);
        if (recv_num < 0)
        {
            printf("recv fail\n");
        }
        else if ( recv_num == 0)/* cli 断开时,recv: Success */
        {
            perror("recv");
            return 0;
        }
        else
        {
            recv_num_total += recv_num;
            printf("recv %d, content:\"%s\",总共字节%d\n", 
                    recv_num, buf, recv_num_total);
        }
    }

    return 0;
}
2 gcc cli.c -o cli
#include 
#include 
#include 
#include 
#include 

#define UN_SOCK_PATH "/home/admin/zzk_tenda/unix_socket/server.socket"

int main(int argc, char *argv[])
{
    int sockfd, ret, send_num, send_num_total = 0;

    char buf[]="unix socketi ~~";
    struct sockaddr_un server_addr;

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strcpy(server_addr.sun_path, UN_SOCK_PATH);
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket");
        return -1;
    }

    ret = connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(server_addr));
    if (ret)
    {
        perror("connect");
        return -1;
    }

    while(1)
    {
        send_num = send(sockfd, buf, sizeof(buf), MSG_DONTWAIT);
        if (send_num < 0)
        {
            printf("send fail\n");
        }
        else
        {
            send_num_total += send_num;
            printf("send %d, content %s, send total %d\n",
                    send_num, buf, send_num_total);
        }
        sleep(2);
    }
    return 0;
}

【编程】unix socket 学习的记录_第1张图片

遇到的问题

在这里发现代码有一些bug,比如当终止client服务时,server端还是会显示,调用recv函数成功。如下所示

查看recv函数的用法可以发现:

当应用程序调用recv函数时,

(1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,

(2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),

recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

上述情况属于网络中断,recv返回的是0。因此只要加上一个判断,当recv返回的数据是0时,则显示网络断开即可。

你可能感兴趣的:(linux,c,网络,linux,c)