UNIX环境高级编程bind()函数绑定sockaddr_un类型出错可能原因

195 阅读3分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路

项目名称

UNIX环境高级编程bind()函数绑定sockaddr_un类型出错可能原因 V1.0.1


目录

1. 项目简介
2. 目录结构
3. 正文
4. 使用说明
5. 维护说明
6. 注意
7. 关于作者
8. 贡献者/贡献组织
9. 鸣谢
10. 版权信息
11. 更新日志

项目简介

目录结构

├── doc	                   		// 项目有关文档
├── File_bak                   	// 项目相关的原始文件,可能包含历史版本等
├── hardware                    // 项目相关的硬件资源文件
├── img             	        // Readme文件或其他文件使用的image文件
├── licenses					// 项目的版权声明或许可证文件
├── program						// 项目的主要代码程序
├── program_test			    // 测试项目的有关程序的代码文件				
├── 参考文档                     // 项目的相关参考文件
├── 测试工具					 // 项目相关用于测试的可用工具
├── 发布版本					 // 已经经过测试,可以发布使用的软件版本
├── Readme.md				   // 当前项目或文件的描述文件

正文

  • 绑定struct sockaddr时,bind函数第三个参数,len不需要计算结构体中使用的长度(截止到文件名称为止),len直接使用整个结构体长度即可,使用sizeof即可,sizeof在编译前就可以得出,省出运行计算时间和代码长度(在bind内部有何影响不知)
    • 修正:bind的size直接使用sizeof或是计算文件路径名得到的结果不一致,有可能有区别,区别不明。书里也没描述清楚
  • bind中的第二个参数文件名必须保证在调用bind前该文件不存在,如果存在会返回-1, 可以先用unlink()函数,该文件的完整目录最好是“正常”的目录,不是目录中的软链接等,尝试使用软链接时亲测返回-1。vmwarework station中的虚拟目录自己可以用ln -s软链接到其他目录,使用这个目录时,便报错了。使用方法中的目录就是在软链接目录中,当使用该目录时bind返回-1。文件路径各方资料中使用绝对目录、相对目录都可以,未测试。使用绝对目录正常。
    • 修正:书中明确指出尽量使用绝对目录,原因是在其他目录调用该文件时将会导致不可预见的错误
  • 源代码
#include "main.h"

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

extern int errno;
/*
    注意:

        必须使用绝对目录
        避开虚拟机共享目录的软连接,硬链接未测试
*/
// static const char file_n[] = "./mysockerunix.txt";
static const char file_n[] = "/home/kira/Desktop/mysockerunix.txt";


int __attribute__((weak)) main(int argc, char* argv[])
{   
    int ret;
    int fd;
    struct sockaddr_un s_un, s_un2;
    
    /* creat unix socket */
    fd = socket(AF_UNIX, SOCK_STREAM, 0);

    s_un.sun_family = AF_LOCAL;
    strcpy(s_un.sun_path, file_n);
    printf("%d, %s\n", s_un.sun_family, s_un.sun_path);
    unlink(file_n);                                                             // 必须保证bind文件前该文件不存在
    if ((ret = bind(fd, (struct sockaddr* )&s_un, sizeof(s_un))) != 0)
        printf("bind erro, %d\n", ret);

    int len = sizeof(s_un2);
    getsockname(fd, (struct sockaddr* )&s_un2, &len);
    printf("s_un2.sun_family = %d, s_un2.sun_path = %s\n", s_un2.sun_family, s_un2.sun_path);

    /* listen */
    listen(fd, 10);

    int pid;
    if ((pid = fork()) > 0)
    {
        int new_fd;
        if ((new_fd = accept(fd, (struct sockaddr* )&s_un, &len)) > 0)
        {
            char mess_ss[100];
            for (int i = 0; i < 10; i++)
            {
                sprintf(mess_ss, "s%02d", i);
                write(new_fd, mess_ss, strlen(mess_ss));
                sleep(1);
            }
        }
        printf("server end\n");
        return 0;
    }
    else if (pid == 0)
    {
        int c_fd;

        c_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
        
        connect(c_fd, (struct sockaddr* )&s_un, sizeof(s_un));

        char mess_c[100];
        for (int i = 0; i < 10; i++)
        {
            read(c_fd, mess_c, 3);
            sleep(1);
            printf("c rec : %s\n", mess_c);
        }

        // remove(file_n);
    }

    return 0;
}

使用说明

  • shell

    kira@kira-virtual-machine:~/Desktop/vm_dir/Project_C_Test$ gcc -o test main.c
    kira@kira-virtual-machine:~/Desktop/vm_dir/Project_C_Test$ ./test
    1, /home/kira/Desktop/mysockerunix.txt
    recv:   s00
    recv:   s01
    recv:   s02
    recv:   s03
    recv:   s04
    recv:   s05
    recv:   s06
    recv:   s07
    recv:   s08
    recv:   s09
    kira@kira-virtual-machine:~/Desktop/vm_dir/Project_C_Test$ 
    

维护说明

注意

关于作者

Autho: KiraSkyler
Email: kiraskyler@outlook.com / kiraskyler@qq.com

贡献者/贡献组织

鸣谢

版权信息

该项目签署了GPL 授权许可,详情请参阅官网
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

更新日志

  • 2021-02-04
    • 使用Readme.md V1.0.0模板
  • 2021-03-08
    • 更新源代码,功能和主题更贴切
    • 修正部分描述,UNIX高级编程和UNIX网络编程代码示例有出入