socket是什么?套接字是什么?

Socket的原意是“插座”。在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

我们把插头插到插座上就能从电网获得电力供应,同样,为了与远程计算机进行数据传输,需要连接到因特网,而 socket 就是用来连接到因特网的工具。
socket的典型应用,就是web服务器和浏览器:浏览器获取用户输入的URL,向服务器发起请求,服务器分析接受到的URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,就将文字和图片,视频等元素呈现给用户。

1.1UNIX/LINUX中的Socket是什么?

在UNIX/LINUX系统中,为了统一各种硬件的操作,简化接口,不同的硬件设备也被看成一个文件,对这些文件的操作,等同于对磁盘上的普通文件的操作。

为了表示和区别已经打开的文件。UNIX/LINUX会给每个文件分配一个ID,这个ID就是一个整数,被称为文件描述符。例如:

  • 通常用0来表示标准输入文件,它对应的硬件设备就是键盘。
  • 通常用1来表示标准输出文件,它对应的硬件设备就是显示器。

UNIX/Linux 程序在执行任何形式的I/O操作,都是在读或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它背后可能只是一个键盘上的普通文件,FIFO,管道,终端,键盘,显示器,甚至是一个网络连接。

请注意,网络连接也是一个文件,它也有文件描述符。

我们可以通过socket()函数来创建一个网络连接,或者说打开一个网络文件。socket()的返回值就是文件描述符。有了文件描述符,我们就可以用普通的文件操作函数来传输数据了。例如:

用read()读取从远程计算机传来的数据。

用write()向远程计算机写入数据。

只要用socket()创建了连接,剩下就是文件操作。

Windows系统中的socket是什么?

Windows也有类似“文件操作符”的概念,但通常被称为“”文件句柄“。

与 UNIX/Linux 不同的是,Windows 会区分 socket 和文件,Windows 就把 socket 当做一个网络连接来对待,因此需要调用专门针对 socket 而设计的数据传输函数,针对普通文件的输入输出函数就无效了。

1.2 通用socket地址

  • socket网络编程接口中表示socket地址的结构体是sockaddr,定义如下

#include <bits/socket.h>
struct sockaddr{
    sa_family_t sa_family;    //地址族类型
    char sa_data[14];        //存放socket地址值
}

sa_family_t:地址族类型,与协议族类型对应 

sa_data用于存放socket地址值

  • 对于PF_UNIX和PF_INET6来说,16字节不够用,所以Linux定义了下边责怪新的通用socket地址结构体:

#include <bits/socket.h>
struct sockaddr_storage{
    sa_family_t sa_family;    //地址族类型
    unsigned long int __ss_align;
    char __ss_padding[128-sizeof(__ss_align)];        
}

这个结构体是内存对齐的,也是就是[128-sizeof(__ss_align)]的作用。编译器创建一个变量时候地址并不是随意取得,而是某一个数的倍数,这样就导致了有一部分内存是用不到的,而上述过程会把申请到的内存刚好用完,这就是内存对齐。

1.3 专用socket地址


通用地址获取IP地址和端口号需要额外操作,Linux提供专门的socket地址结构体
1.3.1 UNIX本地协议族专用socket地址结构体

#include <sys/un.h>
struct sockaddr_un {
    sa_family_t sin_family; //地址族
    char sun_path[108];        //文件路径名
}

1.3.2 TCP/IP协议族专用socket地址结构体
IPv4

struct sockaddr_in {
    sa_family_t sin_family;        //地址族
    u_int16_t sin_port;            //端口号,网络字节序
    struct in_addr sin_addr;    //IPv4地址结构体
}
struct in_addr {
    u_int32_t s_addr;            //IPv4地址,用网络字节序表示
}

IPv6

struct sockaddr_in6 {
    sa_family_t sin6_family;        //地址族
    u_int16_t sin6_port;            //端口号,网络字节序
    u_int32_t sint6_flowinfo;        //流信息,应设置为0
    struct in6_addr sin6_addr;        //IPv6地址结构体
    u_int32_t sin6_scope_id            //scope ID, 处于实验阶段
}
struct in6_addr {
    unsigned char sa_addr[16];            //IPv6地址,用网络字节序表示

所有专用socket地址以及sockaddr_storage类型的变量在实际使用的时候都需要强制转换为通用的socket地址类型sockaddr。因为所有socket编程接口使用的地址参数类型都是sockaddr. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值