本文参考的是《Socket通信原理》https://www.cnblogs.com/wangcq/p/3520400.html

一、TCP/IP UDP是什么?

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。下面是他们三者的关系:

可以看出TCP/IP协议族包括运输层、网络层、链路层。socket是一个接口,在用户进程与TCP/IP协议之间充当中间人,完成TCP/IP协议的书写,用户只需理解接口即可。

二、socket与TCP/IP的对应关系

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

原作者将socket通信类比为打电话这一生活场景。这里我把TCP服务器比作政府某一服务部门能,TCP客户端比作企业中某一部门电话,描述这一过程,恰好就像是socket通信,服务部门提供服务,企业部门申请服务。
要实现通信,首先政府部门都必须申请一个电话(socket_fd),并向有关部门注册(我们的系统),提供地址(sockadrr)以及属于哪个部门的(port),录入系统后,就算是合约生效了(bind),于是乎,政府广而告之,这个服务热线就算开通了,在部门里面的人员所需要做的事情,就是等待企业家拨打热线(listen)。
企业家拨打电话对地点和部门没有这么多的要求了,他并不需要绑定地址和部门,在任何一个可以拨打电话的地方(可能是同个部门,也可以同公司不同部门,甚至可能是竞争对手),他只需要拿起一个已经注册的电话(socket_fd),拨打电话(connect)
政府部门接通电话(accept)后,桥梁就打通了(服务者client_fd、顾客server_fd),可以进行听说了(read write)。企业家咨询完成(close),政府到点下班关闭服务(close)

三、socket API 简单介绍

3.1 socket() 创建socket描述符

int socket(int domain, int type, int protocol);
//成功返回非负描述符,失败返回-1

domain:即协议域,又称为协议族(family)。
常用的地址族有:

  • AF_INET
  • AF_INET6
  • AF_LOCAL(AF_UNIX,本地通信用)
  • AF_ROUTE

协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

type:信息传送方式。

  • SOCK_STREAM
  • SOCK_DGRAM
  • SOCK_RAW
  • SOCK_PACKET
  • SOCK_SEQPACKET

protocol:对应协议。

  • IPPROTO_TCP TCP传输协议
  • IPPROTO_UDP UDP传输协议
  • IPPROTO_SCTP STCP传输协议
  • IPPROTO_TIPCTIPC传输协议
    通常设置为0,让其自动匹配。

我的理解就是:
domain 网络层相关协议 type 信息传送方式 protocol 运输层相关协议,如果前两个都确定了,系统就可以自动选择协议了。

3.2 bind()绑定实际地址

int bind(int sockfd, const struct sockaddr *addr, socklen_t
addrlen);
//返回值:成功则为0,失败为-1

sockfd 一般服务端才需要绑定,客户端由系统内核解决
addr 所有协议都有一个公共的结构叫做const struct sockaddr,不同协议对应不同的具体结构,结构如下:

struct sockaddr {  sa_family_t sin_family;//地址族char sa_data[14]; //14字节,包含套接字中的目标地址和端口信息               };

可以看出,我们端口和目标地址放在同一数组中,不太容易使用。对于不同的协议,我们会通过另一种特定的结构体的来完成初始化,再通过强制类型转换,来使用bind函数。

强制转换第二个地址参数为const sockaddr *

(const sockaddr *)sockaddr_in;
(const sockaddr *)sockaddr_in6;
(const sockaddr *)sockaddr_un;
  • ipv4结构体
struct sockaddr_in {sa_family_t    sin_family; in_port_t      sin_port;   //typedef  __uint16_t      in_port_t;struct in_addr sin_addr;
};struct in_addr {uint32_t       s_addr;
};
  • ipv6结构体
struct sockaddr_in6 { sa_family_t     sin6_family;    in_port_t       sin6_port;      uint32_t        sin6_flowinfo;  struct in6_addr sin6_addr;      uint32_t        sin6_scope_id;
};struct in6_addr { unsigned char   s6_addr[16];
};
  • Unix域结构体
#define UNIX_PATH_MAX    108struct sockaddr_un { sa_family_t sun_family;                char        sun_path[UNIX_PATH_MAX];
};
  • addrlen:协议结构体大小
    通常使用sizeof运算符计算
sizeof(sockaddr_in);//IPv4 in:internet
sizeof(sockaddr_in6);//IPv6
sizeof(sockaddr_un);//本地 un:unix

3.3 listen()、connect() 主机监听、从机链接

int listen(int sockfd, int backlog);
//返回值:成功则为0,失败为-1
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//返回值:成功则为0,失败为-1

listen决定需要开启的部门热线,connect拨打电话。

listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

3.4 accept 建立链接

只要服务端建立链接,我们就可以进行操作了

int accept(int sockfd, struct sockaddr *addr, socklen_t  *addrlen);
//返回值:成功则为0,失败为-1

第一个参数为服务器的socket描述字,
第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址
第三个参数为协议地址的长度。

如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。后面的读写操作都是根据这个返回值来完成的。

3.5 read和write函数,读写

这不是属于socket的API,但是socket总是伴随着以下函数:

ssize_t read(int fd, void *buf, size_t count);ssize_t write(int fd, const void *buf, size_t count);ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节 数。失败时返回-1,并设置errno变量。在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是 全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示 网络连接出现了问题(对方已经关闭了连接)。

3.6 close关闭服务

int close(int fd);
//返回值:成功则为0,失败为-1

close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

Socket的学习(一)什么是Socket?相关推荐

  1. socket编程学习(addr设置)

    sockaddr结构体 struct  sockaddr{ sa_family_t  sa_family; //地址族,最常用的是"AF_INET"(IPV4)和"AF_ ...

  2. linux socket ip层配置,Linux下Socket通信(TCP实现)

    近期在做的项目中,涉及到了进程间数据传输,系统的原本实现是通过管道,但是原有的实现中两个进程是在同一台机器,而且两个进程的关系为父子关系,而我们要做的是将其中一个进程移植到服务器上,因此两个进程要分开 ...

  3. c++服务器开发学习--01--c++基础,socket

    c++服务器开发学习--01--c++基础,socket c++基础 问题 记录内容 socket c++基础 学习链接:w3cschool,博客中只记录了博主感到疑问和重要的内容. 问题 byte类 ...

  4. python socket服务器_python网络编程学习笔记(三):socket网络服务器

    1.TCP连接的建立方法 客户端在建立一个TCP连接时一般需要两步,而服务器的这个过程需要四步,具体见下面的比较.步骤 TCP客户端 TCP服务器 第一步 建立socket对象 建立socket对象 ...

  5. Socket通信学习(二):序列化与反序列化

    Socket通信学习(二):序列化与反序列化 HoloLens的开发最近需要用到Socket通信,所以创建本系列进行记录,欢迎大家批评指正! 前言 Socket通信的默认发送的数据为byte[]类型, ...

  6. Socket通信学习(一):Socket通信原理

    Socket通信学习(一):Socket通信原理 HoloLens的开发最近需要用到Socket通信,所以创建本系列进行记录,欢迎大家批评指正! 前言 应用Socket进行设备通信,首先需要了解Soc ...

  7. Java网络编程socket基础学习

    文章目录 InetAddress类 URL类 URLConnection类 使用URLConnection发送post请求 Socket类 DatagramSocket MulticastSocket ...

  8. Python学习,python中socket解读

    操作系统底层原理 操作系统:(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在"裸机"上的最基本的系统软件,任何其他软件都必须 ...

  9. Socket编程学习-基础操作

    Socket编程学习-基础操作 socket的基本操作 可参考,https://blog.csdn.net/sinat_36645384/article/details/79128137 核心问题1- ...

  10. 网络编程学习笔记一:Socket编程

    "一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信 ...

最新文章

  1. Mysql之主从复制及主主复制
  2. windows下怎么安装protobuf for python
  3. php.ini 配置详解
  4. 友盟+《小程序用户增长白皮书》:从五个角度入手分析小程序数据
  5. linux基础命令下载,Linux基础命令教程豪华版
  6. 接口做的好怎么形容_淘宝直播预告怎么做才合格?如何做好?
  7. Android 内存泄漏之handler
  8. promise then返回值
  9. mysql,sqlserver数据库单表数据过大的处理方式
  10. 时间序列分析(11)| 向量自回归模型(VAR模型)
  11. 径向基和径向基神经网路
  12. Matlab一维数据的中值滤波与均值滤波函数
  13. 人工智能对智能建筑有哪些影响,智能建筑发展存在哪些问题?
  14. 从远程服务器下载文件
  15. java采用降低图片分辨率大小来压缩图片大小
  16. C1083: 无法打开包括文件: plugin.moc: No such file or directory
  17. 图像处理:U-Net中的重叠-切片(Overlap-tile)
  18. 一起来学SpringBoot(十)缓存的使用
  19. 学习使用HTML+CSS完成一个私人网页
  20. 高德地图我的队伍查岗_高德地图查岗新功能 让你的行踪无所遁形

热门文章

  1. 出售黄金外汇交易平台,商机就是投机!
  2. WebGL坐标系介绍
  3. 【深度学习前沿应用】文本分类Fine-Tunning
  4. suffix word ality ally an ancy ance an aneity out ~1
  5. NetSuite几个Amount的含义
  6. 新东方财报:教育稳行、电商爆走、学习硬件加速
  7. 在 Scala 中读取整个文件
  8. switch参数支持的类型
  9. 终极求生手机(待机15年的)
  10. 【Flink 实战系列】Flink SQL 使用 filesystem connector 同步 Kafka 数据到 HDFS(parquet 格式 + snappy 压缩)