在看 socket,有点困惑

2015-12-28 20:12:22 +08:00
 fyyz
http://www.cnblogs.com/L-hq815/archive/2012/07/09/2583043.html
第四段:结构体


1 ,“ socket 描述符”是结构体 sockaddr 中的 sa_family 吗?
2 , sa_data[14]; 这到底是啥玩意?这串数组里存的“ 14 字节协议地址”究竟是什么?
3 ,文章里面说 struct sockaddr 和 struct sockaddr_in 是并列的,但是我看来都是大小不一样啊。


实在看不懂,反反复复看了好几遍,希望高人解答。
1683 次点击
所在节点    C
11 条回复
xufang
2015-12-28 20:33:32 +08:00
呃, socket 光看博客是看不会哒,从 UNP 看起吧。
LXJ
2015-12-28 20:45:18 +08:00
socket 描述符类似 file descriptor ,并不是 sa_family ;

除 UNP 外,推荐《 TCP/IP Sockets in C, Second Edition 》这本小书,里面有关于 socket 编程一步步的讲解,有可运行的示例代码,也有对示例代码细致的讲解。
fyyz
2015-12-28 20:49:00 +08:00
@LXJ C++也是一样吗?
LXJ
2015-12-28 21:02:25 +08:00
@fyyz 应该一样;这里主要还是讲解 Socket 编程,和语言关系不大。
hitmanx
2015-12-28 21:02:52 +08:00
2. sa_data[14]; 这到底是啥玩意?这串数组里存的“ 14 字节协议地址”究竟是什么?
3 ,文章里面说 struct sockaddr 和 struct sockaddr_in 是并列的,但是我看来都是大小不一样啊。


我已经忘得差不多了=.=,但是看了一下你的那篇文章,感觉是这个意思:

struct sockaddr {
   unsigned short sa_family; /* 地址家族, AF_xxx */
   char sa_data[14]; /*14 字节协议地址*/
};

struct sockaddr_in {
   short int sin_family; /* 通信类型 */
   unsigned short int sin_port; /* 端口 */
   struct in_addr sin_addr; /* Internet 地址 */
   unsigned char sin_zero[8]; /* 与 sockaddr 结构的长度相同*/
};

文中的意思是这两个结构体是等效的,可以看到除了共同的 sa_family 以外,上面的 sa_data 为 14 字节,下面的端口(2 字节) + ipv4 的地址(4 字节) + char[8],刚好也是 14 字节.
billlee
2015-12-28 21:13:30 +08:00
1. socket 的 API 来源于 BSD. 在 Unix 下, 一切皆文件, socket 描述符是文件描述符的一种,就是一个整数。
2. socket 有很多类型,不同类型的 socket 的地址结构也是不一样的。你可以理解为 struct sockaddr 是一个抽象类, sa_data 是给子类特有的字段留的空间。
fyyz
2015-12-28 21:17:45 +08:00
谢谢楼上各位的解答。其实看了各位的解答感觉还是有点一知半解,准备买本 UNP 看看。
shyling
2015-12-28 21:59:33 +08:00
描述符全是数字=。=
elgoog1970
2015-12-28 22:26:14 +08:00
lz 问的问题,实在让这些码农无法回答,还是先学习下网络,在看看《 unix 网络编程》,并把上面的代码练习下,最后写个简单的 FTP 或者 chat-tool ,那 lz 就对 socket 方面的知识有所了解了:)
k9982874
2015-12-28 23:55:19 +08:00
第一个问题 sock 描述符是一个文件句柄 /描述符, sockaddr 结构是创建 sock 时需要的参数
其他问题 5 楼给了正解
codesun
2015-12-29 11:43:43 +08:00
linux 的头文件里解释得挺清楚的:

旧的声明,为何是 14 ,可以参考‘ talk ’协议
/* This is the 4.3 BSD `struct sockaddr' format, which is used as wire
format in the grotty old 4.3 `talk' protocol. */
struct osockaddr
{
unsigned short int sa_family;
unsigned char sa_data[14];
};

如下是新的声明,总体长度不变
/* Structure describing a generic socket address. */
struct sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
};

如下为 ipv4 的 sockaddr ,明确说明需要填充至 sockaddr 的长度
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */

/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
至于为何提供 sockaddr 和 sockaddr_in ,按照我个人的理解,是因为历史原因,比如‘ talk ’,其次,现在除了上述 2 个 sockaddr ,还有供 ipv6 使用的 sockaddr_in6 ,那么为了保证 API 的向下兼容, sockaddr 反而成了一种抽象表示,但 C 并不提供类似的语法,因此只能使用相对暴力的强制转型了(前提是保证 struct 内部变量的偏移一致),使用的时候只需要根据 sa_family 即可判断到底是 ipv4 还是 ipv6

另文件描述符即 fd ,就是 socket()的返回值,它是一个索引,即一个整形

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/246760

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX