首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux系统下socket编程socket接口介绍(二)

Linux系统下socket编程socket接口介绍(二)

作者头像
用户6280468
发布于 2022-03-18 12:56:36
发布于 2022-03-18 12:56:36
4.2K00
代码可运行
举报
文章被收录于专栏:txp玩Linuxtxp玩Linux
运行总次数:0
代码可运行

前言

在上一篇文章里面我们介绍了TCP的三次握手和四次挥手过程的介绍以及网络编程里面的一些api接口函数的介绍——Linux系统下socket编程之socket接口介绍(一)。今天我们继续来介绍网络编程里面的其它接口函数,为实战打下 基础;网络编程专题文章拖的有点久,这两天全部把它写完,不能再拖了。

函数介绍

- 发送和接收 -

(1)send和write:

首先说明的一点,之前介绍的socket这个函数,非常类似我们之前介绍的open函数,他们都会返回一下文件描述符;所以这里的send函数和write函数作用类似,我们用man手册来查看它的具体形式和用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   #include <sys/types.h>
   #include <sys/socket.h>

   ssize_t send(int sockfd, const void *buf, size_t len, int flags);

说明:

第一个参数sockfd就是socket函数返回的文件描述符;第二个参数指向发送的信息所在的缓冲区(内存);第三个参数指缓冲区的长度大小;第四个参数一般设置为0(如果不是这种情况,可以具体再查看)。不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。

(2)recv和read:

函数recv和之前介绍的read函数的用法差不多,我们还是用man手册来查看一它的形式和用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   #include <sys/types.h>
   #include <sys/socket.h>

   ssize_t recv(int sockfd, void *buf, size_t len, int flags);

说明:

这里面的参数和上面send的参数说明一样。不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。

- IP地址格式转换函数 -

(1)inet_aton、inet_addr、inet_ntoa(只用IPV4的IP地址),现在用的比较少,不过大多程序里面会看到这些函数,所以还是要学习一下它的作用,老方法使用man手册来查看它的形式和用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <arpa/inet.h>

   int inet_aton(const char *cp, struct in_addr *inp);

   in_addr_t inet_addr(const char *cp);

   in_addr_t inet_network(const char *cp);

   char *inet_ntoa(struct in_addr in);

   struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);

   in_addr_t inet_lnaof(struct in_addr in);

   in_addr_t inet_netof(struct in_addr in);

说明:

首先我们来看inet_aton函数,它转换网络主机地址ip(如192.168.1.10)为二进制数值,并存储在struct in_addr结构中,即第二个参数*inp,函数返回非0表示cp主机有地有效,返回0表示主机地址无效。(这个转换完后不能用于网络传输,还需要调用htons或htonl函数才能将主机字节顺序转化为网络字节顺序,这两个函数先不讲,实战遇到的话,再进行解析),具体可以看下面Linux的源文:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 inet_aton()  converts  the  Internet  
host  address  cp  from  the  IPv4  
numbers-and-dots notation into binary 
form (in network byte order) and stores it in the 
 structure that inp points to.
   inet_aton() returns nonzero if the address is valid, 
   zero if not.  The address 
 supplied in cp can have one of the following forms:

   a.b.c.d   Each of the four numeric parts specifies a 
  byte of the address; the 
 bytes are assigned in left-to-right order to produce the binary address.

   a.b.c     Parts a and b specify the first two bytes of the binary address.  Part c is interpreted as a 16-bit value that defines the rightmost two bytes of the binary address.  This  notation
             is suitable for specifying (outmoded) Class B network addresses.

   a.b       Part a specifies the first byte of the binary address.  Part b is 
  interpreted as a 24-bit value that defines the
  rightmost three bytes of the binary address.  This notation is suit‐
             able for specifying (outmoded) Class A network addresses.

   a         The value a is interpreted as a 32-bit value that is stored 
   directly into the binary address without any byte rearrangement.

   In all of the above forms, components of the dotted address can be specified
    in decimal, octal (with a leading 0), or hexadecimal, with a leading 0X). 
    Addresses in any  of  these  forms  are
   collectively termed IPV4 numbers-and-dots notation.  The form that uses exactly
    four decimal numbers is referred to as IPv4 dotted-decimal notation (or sometimes: IPv4 dotted-quad notation).

   inet_aton() returns 1 if the supplied string was successfully interpreted, 
  or 0 if the string is invalid (errno is not set on error).

接着是inet_addr函数,它的作用主要是转换网络主机地址(如192.168.1.10)为网络字节序二进制值,如果参数char *cp无效,函数回-1(INADDR_NONE),这个函数在处理地址为255.255.255.255时也返回-1,255.255.255.255是一个有效的地址,不过inet_addr无法处理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   The  inet_addr()  function converts the Internet 
   host address cp from IPv4 numbers-and-dots notation into 
   binary data in network byte order.  
   If the input is invalid, INADDR_NONE (usually -1)
   is returned.  
   Use of this function is problematic because -1 is a 
  valid address (255.255.255.255). 
   Avoid its use in favor of inet_aton(), inet_pton(3), 
   or  getaddrinfo(3),  which  provide  a
   cleaner way to indicate error return.

最后就是inet_ntoa函数,它的作用主要是转换网络字节排序的地址为标准的ASCII以点分开的地址,该函数返回指向点分开的字符串地址(如192.168.1.10)的指针,该字符串的空间为静态分配的,这意味着在第二次调用该函数时,上一次调用将会被重写(复盖),所以如果需要保存该串最后复制出来自己管理!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 The inet_ntoa() function converts the Internet host 
 address in, given in network byte order, to a string in 
 IPv4 dotted-decimal notation.  The string is returned  
 in  a  statically  allocated
   buffer, which subsequent calls will overwrite.

(2)inet_ntop、inet_pton,这两个函数是随IPv6出现的函数,对于IPv4地址和IPv6地址都适用,函数中p和n分别代表表达(presentation)和数(numeric)。地址的表达格式通常是ASCII字符串,数值格式则是存放到套接字地址结构的二进制值。我们还是用man手册来查看的它们的形式和作用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  #include <arpa/inet.h>

   const char *inet_ntop(int af, const void *src,  char *dst, socklen_t size);

我们先来看inet_ntop这个函数,第一个参数表示地址族(就是ipv4和ipv6),它的作用是把二进制格式转化为点分十进制的ip地址格式;inet_ntop函数的dst参数不可以是一个空指针。调用者必须为目标存储单元分配内存并指定其大小,调用成功时,这个指针就是该函数的返回值。size参数是目标存储单元的大小,以免该函数溢出其调用者的缓冲区。如果size太小,不足以容纳表达式结果,那么返回一个空指针,并置为errno为ENOSPC:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   This  function  converts  the  network address 
   structure src in the af address family into a 
   character string.  The resulting string is copied to 
   the buffer pointed to by dst, which must be a
   non-null pointer.  The caller specifies the number of 
   bytes available in this buffer in the argument size.

   inet_ntop() extends the inet_ntoa(3) function to 
   support multiple address families, inet_ntoa(3) is 
   now considered to be deprecated in favor of 
   inet_ntop().  The  following  address  families
   are currently supported:

   AF_INET
          src  points  to a struct in_addr (in network 
   byte order) which is converted to an IPv4 network 
  address in the dotted-decimal format, 
  "ddd.ddd.ddd.ddd".  The buffer dst must be at least
          INET_ADDRSTRLEN bytes long.

   AF_INET6
          src points to a struct in6_addr (in network 
   byte order) which is converted to a representation of 
   this address in the most appropriate IPv6 network 
   address  format  for  this  address.
          The buffer dst must be at least 
 INET6_ADDRSTRLEN bytes long.

 RETURN VALUE
   On success, inet_ntop() returns a non-null pointer to 
  dst.  NULL is returned if there was an error, with 
  errno set to indicate the error.

ERRORS
   EAFNOSUPPORT
          af was not a valid address family.

   ENOSPC The converted address string would exceed the 
   size given by size.

接着我们来看inet_pton函数,它的作用主要是将点分十进制的ip地址转化为二进制格式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  #include <arpa/inet.h>

   int inet_pton(int af, const char *src, void *dst);

DESCRIPTION
   This  function  converts  the character string src 
  into a network address structure in the af address 
  family, then copies the network address structure to 
  dst.  The af argument must be either
   AF_INET or AF_INET6.  dst is written in network byte 
  order.

   The following address families are currently 
supported:

   AF_INET
          src points to a character string containing an 
  IPv4 network address in dotted-decimal format, 
  "ddd.ddd.ddd.ddd", where ddd is a decimal number of up 
  to three digits in the range  0  to
          255.  The address is converted to a struct 
  in_addr and copied to dst, which must be sizeof(struct 
  in_addr) (4) bytes (32 bits) long.

   AF_INET6
          src  points to a character string containing 
   an IPv6 network address.  The address is converted to 
   a struct in6_addr and copied to dst, which must be 
   sizeof(struct in6_addr) (16) bytes
          (128 bits) long.  The allowed formats for IPv6 
   addresses follow these rules:

          1. The preferred format is x:x:x:x:x:x:x:x.  
   This form consists of eight hexadecimal numbers, each 
   of which expresses a 16-bit value (i.e., each x can 
   be up to 4 hex digits).

          2. A series of contiguous zero values in the 
   preferred format can be abbreviated to ::.  Only one 
   instance  of  ::  can  occur  in  an  address.   For  
   example,  the  loopback  address
             0:0:0:0:0:0:0:1 can be abbreviated as ::1.  
   The wildcard address, consisting of all zeros, can be 
  written as ::.

          3. An  alternate  format  is useful for 
 expressing IPv4-mapped IPv6 addresses.  This form is 
 written as x:x:x:x:x:x:d.d.d.d, where the six leading 
 xs are hexadecimal values that define
             the six most-significant 16-bit pieces of 
 the address (i.e., 96 bits), and the ds express a value 
 in dotted-decimal notation that defines  the  least  
 significant  32  bits  of  the
             address.  An example of such an address is 
 ::FFFF:204.152.189.116.

          See RFC 2373 for further details on the 
 representation of IPv6 addresses.

RETURN VALUE
   inet_pton()  returns 1 on success (network address 
 was successfully converted).  0 is returned if src does 
 not contain a character string representing a valid 
 network address in the specified
   address family.  If af does not contain a valid 
 address family, -1 is returned and errno is set to 
EAFNOSUPPORT.

- 表示IP地址相关数据结构 -

(1)上面的一些函数参数里面用到的结构体(比如bind函数参数里的const struct sockaddr *addr等)都定义在 netinet/in.,我们可以用 vim /usr/include/netinet/in.h 来查看,这里具体的我就不理出来了,里面的内容比较多。

(2)struct sockaddr,这个结构体是linux的网络编程接口中用来表示IP地址的

标准结构体,bind、connect等函数中都需要这个结构体,这个结构体是兼容IPV4和IPV6的。在实际编程中这个结构体会被一个struct sockaddr_in或者一个struct sockaddr_in6所填充。

(3)typedef uint32_t in_addr_t:网络内部用来表示IP地址的类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(4)struct in_addr
    {
       in_addr_t s_addr;
    };
(5)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)];
   };

总结

今天主要是介绍了一下函数用法,下一篇文章开始进入实战讲解!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 txp玩Linux 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结
210.25.132.181属于IP地址的ASCII表示法,也就是字符串形式。英语叫做IPv4 numbers-and-dots notation。
阳光岛主
2019/02/20
6.5K0
linux网络编程系列(二)
套接字,也叫socket,是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户。网络通信,说白了就是进程间的通信(同一台机器上不同进程或者不同计算机上的进程间通信)。
cpp加油站
2021/04/16
9960
linux网络编程之socket(一):socket概述和字节序、地址转换函数
s1mba
2017/12/28
2.4K0
linux网络编程之socket(一):socket概述和字节序、地址转换函数
UNIX网络编程卷1(第三版)套接字编程简介
  通常也被成为“网际套接字地址结构”,以sockaddr_in命名,定义在<netinet/in.h>头文件中。 
心跳包
2020/08/31
8820
IPv4地址的结构体与网络字节序
sin_family: 每种协议族使用的地址族均不同,IPv4使用4字节地址族,IPv6使用16字节地族。
玖柒的小窝
2021/12/15
8230
UNPv1第三章:套接字编程简介
1).IPv4套接字地址结构 IPv4套接字地址结构通常也称为“网际套接字地址结构”,它以sockaddr_in命名,定义在
提莫队长
2019/02/21
1.1K0
socket 编程--sockaddr与sockaddr_in区别与联系(转)
在linux环境下,结构体struct sockaddr在/usr/include/linux/socket.h中定义,具体如下: typedef unsigned short sa_family_t; struct sockaddr { sa_family_t sa_family; /* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ 在linux环境下,结构体struct sockaddr_in在/usr/include/netinet/in.h中定义,具体如下: /* 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)]; /* 字符数组sin_zero[8]的存在是为了保证结构体struct sockaddr_in的大小和结构体struct sockaddr的大小相等 */ }; struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。 下面是struct sockaddr_in中用到两个数据类型,具体定义如下: /* Type to represent a port. */ typedef uint16_t in_port_t; struct in_addr其实就是32位IP地址 struct in_addr { unsigned long s_addr; }; BSD网络软件中包含了两个函数,用来在二进制地址格式和点分十进制字符串格式之间相互转换,但是这两个函数仅仅支持IPv4。 in_addr_t inet_addr(const char *cp); char *inet_ntoa(struct in_addr in); 功能相似的两个函数同时支持IPv4和IPv6 const char *inet_ntop(int domain, const void *addr, char *str, socklen_t size); int inet_pton(int domain, const char *str, void *addr); 通常的用法是: int sockfd; struct sockaddr_in my_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; /* 主机字节序 */ my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */ my_addr.sin_addr.s_addr = inet_addr("192.168.0.1"); bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */ //memset(&my_addr.sin_zero, 0, 8); bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
jianghaibobo
2019/09/11
2.2K0
【网络编程】Linux网络编程基础与实战第二弹——Socket编程
Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。
洁洁
2023/10/19
5030
【网络编程】Linux网络编程基础与实战第二弹——Socket编程
UNPv13:#第3章#套接字编程简介
IPv4套接字地址结构 POSIX规范只要求3个字段:sin_family、sin_addr和sin_port。 #include <netinet/in.h> struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; ... }; 通用套接
_gongluck
2018/03/09
8140
网络套接字、网络字节序、sockaddr结构
Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。
mindtechnist
2025/02/12
1770
网络套接字、网络字节序、sockaddr结构
Linux网络编程API(一)
htonl即”host to network long”, 即长整型(32bit)的主机字节序转换未网络字节序数据。
doper
2022/09/26
1.5K0
Linux网络编程API(一)
2021版!万字UNIX网络编程学习笔记(套接字篇)
#2.直接编译 gcc -o 1.out daytimetcpcli.c #错误提示如下: daytimetcpcli.c:1:17: fatal error: unp.h: No such file or directory #include "unp.h" ^ compilation terminated. #在../key目录下找到unp.h。继续提醒没有<sys/fiflo.h>从网上下载继续出问题。
心跳包
2021/09/26
1.1K0
2021版!万字UNIX网络编程学习笔记(套接字篇)
socket inet_pton
inet_pton   Linux下这2个IP地址转换函数,可以在将IP地址在“点分十进制”和“整数”之间转换   而且,inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6。算是比较新的函数了。   inet_pton函数原型如下[将“点分十进制” -> “整数”]   #include <sys/types.h>   #include <sys/socket.h>   #include <arpa/inet.h>   int inet_pton(int af, const char
cloudskyme
2018/03/20
2.5K0
套接口编程
1 struct in_addr{ 2 in_addr_t s_addr; 3 }; 4 struct sockaddr_in{ 5 uint8_t sin_len; 6 sa_family_t sin_family; 7 in_port_t sin_port; 8 9 struct in_addr sin_addr; 10 char sin_zero[8]; 11 }; 通用套接口地址结构: struct sockaddr{ u
用户1154259
2018/01/17
5420
一文搞懂网络套接字编程
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。
海盗船长
2020/08/27
6570
自己实现inet_aton和inet_ntoa函数功能
之前遇到过要自己实现inet_aton和inet_ntoa函数功能的问题,这里总结一下。
typecodes
2024/03/29
5250
自己实现inet_aton和inet_ntoa函数功能
socket:Python网络通信套接字
socket库提供了一个底层C API,可以使用BSD套接字接口实现网络通信。它包括socket类,用于处理具体的数据通道,还包括用来完成网络相关任务的函数,如将一个服务器名转换为一个地址以及格式化数据以便在网络上发送。
luckpunk
2023/09/29
3680
socket:Python网络通信套接字
linux下Socket编程(一)简介
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现, socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。 说白了Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。 注意: 其实socket也没有层的概念,它只是一个facade设计模式的应用,让编程变的更简单。是一个软件抽象层。在网络编程中,我们大量用的都是通过socket实现的。
用户2929716
2018/08/23
3.8K0
linux下Socket编程(一)简介
套接口编程简介
每个协议族都定义了自己的套接口地址结构,名字均以sockaddr_开头,对应协议族的标志结束。大部分套接口函数需要指向套接口地址结构的指针作为参数。
jackieluo
2018/09/03
1.2K0
套接口编程简介
【Socket】Socket相关概念及函数
Socket中文意思是"插座",在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。
半生瓜的blog
2023/05/13
9600
【Socket】Socket相关概念及函数
推荐阅读
相关推荐
Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档