Socket的学习(一)什么是Socket?

Socket的学习(一)什么是Socket?本文参考的是 Socket 通信原理 https www cnblogs com wangcq p 3520400 htmlTCP IPUDP 是什么 TCP IP Transmission InternetProt 即传输控制协议 网间协议 是一个工业标准的协议集 它是为广域网 WANs 设计的 UDP UserDataProt

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

一、TCP/IP UDP是什么?

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

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

socket3

三、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,让其自动匹配。

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 108 struct 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  

如果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客户端向服务器发送终止连接请求。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/215651.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午1:45
下一篇 2026年3月18日 下午1:45


相关推荐

  • transferto方法的应用_Java MultipartFile.transferTo方法代碼示例

    transferto方法的应用_Java MultipartFile.transferTo方法代碼示例本文整理匯總了 Java 中 org springframew web multipart MultipartFil transferTo 方法的典型用法代碼示例 如果您正苦於以下問題 JavaMultipar transferTo 方法的具體用法 JavaMultipar transferTo 怎麽用 JavaMultipar transferTo 使用的例子 那麽

    2026年3月16日
    1
  • C++优先队列_队列queue中添加元素的方法

    C++优先队列_队列queue中添加元素的方法1.优先级队列(priority_queue)1.1基本概念之前已经提到了队列(queue),队列是一种先进先出(FirstinFirstout,FIFO)的数据类型。每次元素的入队都只能添加到队列尾部,出队时从队列头部开始出。优先级队列(priority_queue)其实,不满足先进先出的条件,更像是数据类型中的“堆”。优先级队列每次出队的元素是队列中优先级最高的那个元素,而不是队首的元素。这个优先级可以通过元素的大小等进行定义。比如定义元素越大优先级越高,那么每次出队,都是将当前队.

    2026年2月25日
    4
  • WebViewJavascriptBridge浅析

    WebViewJavascriptBridge浅析WebViewJavas 是一个 Objective C 与 JavaScript 进行消息互通的三方库 通过 WebViewJavas 我们可以很方便的实现 OC 和 Javascript 互调的功能 WebViewJavas 实现互调的过程也容易理解 就是在 OC 环境和 Javascript 环境各自保存一个相互调用的 bridge 对象 每一个调用之间都有 i

    2026年3月20日
    2
  • Swift 启动页动画(CAKeyframeAnimation)

    Swift 启动页动画(CAKeyframeAnimation)

    2021年5月27日
    155
  • 建站指南和Web开发经验

    建站指南和Web开发经验建站指南和 Web 开发经验 1 php 学习经验 2 网站流量统计代码选择经验 3 新手入门 如何学习 PHP 之经验谈 4 Web 开发经验几则 5 关于 web 应用程序安全的思考 6 与戴志康 陈浩畅谈 PHP7 NET 和 J2EE 该相互学习什么 8

    2026年3月17日
    2
  • 足迹地图 搜索jvectormap

    足迹地图 搜索jvectormap

    2021年10月28日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号