本文已参与[新人创作礼]活动,一起开启掘金创作之路
项目名称
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网络编程代码示例有出入