UNP学习笔记(第三章:套接字编程简介)

本章开始讲解套接字API。

套接字地址结构

IPv4套接字地址结构

它以sockaddr_in命名,下面给出它的POSIX定义

struct in_addr
{
     in_addr_t s_addr;
};

stuct sockaddr_in
{
     uint8_t         sin_len;
     sa_family_t     sin_family;    /* AF_INET */
     in_port_t       sin_port;
     struct in_addr  sin_addr;
     char            sin_zero[8];
};

POSIX规范只需要这个结构中的3个字段:sin_family、sin_port和sin_addr。

下图列出了POSIX定义的关于socket编程的数据类型

通用的套接字地址结构

为了解决任意套接字地址结构都可以传递进使用套接字地址的套接字函数中,定义了一个通用的套接字地址结构。

任何套接字地址结构的指针都通过类型强制转换(变成通用套接字地址结构的指针)来做为函数参数。

通用的套接字地址结构如下所示

struct sockaddr
{
    uint8_t        sa_len;
    sa_family_t    sa_family;
    char           sa_data[14];
};

IPv6套接字地址结构

struct in_addr
{
     in_addr_t     s_addr;
};

struct sockaddr_in
{
     uint8_t            sin_len;
     sa_family_t        sin_family;       /* AF_INET6 */
     in_port_t          sin_port;
     struct in_addr     sin_addr;
     char               sin_zero[8];
};

字节排序函数

网络字节序采用大端字节序,而不同主机使用不同的字节序。

下面4个函数用于主机字节序和网络字节序之间的相互转换

#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
                                           //均返回:网络字节序的值;
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);
                                           //均返回:主机字节序的值;

h代表host,n代表network,s代表short,l代表long。

字节操纵函数

下面函数用于字节的设置、复制和比较。

#include <strings.h>
void bzero(void *dest, size_t nbytes);
void bcopy(const void *src, void *dest, size_t nbytes);
void bcmp(const void *ptr1, const void *ptr2, size_t nbytes);
                                     //返回:相等则为0,否则为非0
#include <string.h>
void *memset(void *dest, int c, size_t nbytes);
void *memcpy(void *dest, const void *src, size_t nbytes);
int   memcmp(const void *s1, const void *s2, size_t nbytes);
                                    //返回:相等则为0,否则为非0

函数inet_aton、inet_addr和inet_ntoa

这几个函数用于在点分十进制数串(如“206.168.112.96”)于它长度为32位的网络字节序二进制值间转换IPv4地址。

#include <arpa/inet.h>
int_addr_t inet_addr(const char *strptr);
                //已被舍弃,使用inet_aton函数代替
int inet_aton(const char *strptr, struct in_addr *addrptr);
                //返回:字符串有效返回1,否则为0
char *inet_ntoa(struct in_addr inaddr);
                //返回:指向一个点分十进制的字符串的指针

函数inet_pton和inet_ntop

相对于上面的几个函数,这两个函数对于IPv4地址和IPv6地址都适用

#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
                                      //返回:若成功返回1,输入不是有效表达格式返回0,若出错返回-1
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
                                       //返回:若成功则返回指向结果的指针,出错则为NULL

p代表表达(presentation)  n代表数值(numeric)

family参数既可以是AF_INET,也可以是AF_INET6。

inet_pton尝试转换由strptr指针指向的字符串,并通过addrptr指针存放二进制结果。

inet_ntop进行相反的转换,len参数是目标储存单元的大小,以免该函数一处其调用者的缓冲区。对此,<netinet/in.h>头文件中由如下定义:

#define INET_ADDRSTRLEN            16
#define INET6_ADDRSTRLEN           46        

UNP中定义的几个函数

inet_ntop函数的一个基本问题是:要求调用者必须知道这个结构的格式和地址族

我们可以使用自己定义的sock_ntop函数来解决这个问题

#include "unp.h"
char *sock_ntop(const struct sodkaddr *sockaddr, socklen_t addrlen);

该函数内部使用sockaddr指针来确定地址族,然后调用inet_ntop。

同样的,我们为操作套接字地址结构定义了如下几个函数

readn、writen和readline函数

字节流套接字(例如TCP套接字)上read和write函数所表现的行为不同于通常的文件

字节流套接字上调用read或write输入或输出的字节数可能比请求的数量上,然而这不是出错的状态,此时所需的是调用者再次调用read或write函数,以输入或输出剩余的字节。

我们提供一下3个函数是每当我们读或写一个字节流套接字时总要使用的函数

#include "unp.h"
ssize_t readn(int filedes,void *buff,size_t nbytes);
ssize_t writen(int filedes,const void *buff,size_t nbytes);
ssize_t readline(int filedes,void *buff,size_t nbytes);
                         //返回值:读或写的字节数,若出错则为-1

readn实现代码

 1 #include "unp.h"
 2 ssize_t readn(int fd,void *vptr,size_t n)
 3 {
 4     size_t  nleft;
 5     ssize_t nread;
 6     char *ptr;
 7
 8     ptr = vptr;
 9     nleft = n;
10     while(nnleft > 0)
11     {
12         if((nread = read(fd,ptr,nleft)) < 0 )
13         {
14             if(errno == EINTR)
15             {
16                 nread = 0;
17             }
18             else
19             {
20                 return -1;
21             }
22         }
23         else if(nread == 0)
24         {
25             break;
26         }
27         nleft -= nread;
28         ptr += nread;
29     }
30     return (n-nleft);
31 }

writen实现代码

 1 #include "unp.h"
 2 ssize_t written(int fd,void *vptr,size_t n)
 3 {
 4     size_t nleft;
 5     ssize_t nwritten;
 6     const char *ptr;
 7     ptr = vptr;
 8     nleft = n;
 9     while(nlfet >  0)
10     {
11         if((nwritten = writen(fd,ptr,nleft)) <= 0)
12         {
13             if(nwritten < 0 && errno ==EINTR)
14             {
15                 nwritten =0;
16             }
17             else
18             {
19                 return -1;
20             }
21         }
22
23         nleft -= nwritten;
24         ptr += nwritten;
25     }
26     return n;
27 }

readline实现代码

 1 #include "unp.h"
 2 ssize_t readline(int fd, void *vptr, size_t maxlen)
 3 {
 4      ssize_t n,rc;
 5      char    c,*ptr;
 6
 7      ptr = vptr;
 8      for(n = 1; n < maxlen; n++)
 9      {
10        if( (rc = read(fd, &c)) == 1)
11        {
12          *ptr ++ = c;
13          if(c == ‘\n‘)
14            break;
15        }
16        else if (r c== 0)
17        {
18           *ptr = 0;
19           return (n-1);
20        }else
21           return (-1);
22      }
23
24      *ptr = 0;
25      return (n);
26 } 

时间: 2024-12-21 10:26:16

UNP学习笔记(第三章:套接字编程简介)的相关文章

UNIX网络编程笔记(2)—套接字编程简介

套接字编程概述 说到网络编程一定都离不开套接字,以前用起来的时候大多靠记下来它的用法,这一次希望能理解一些更底层的东西,当然这些都是网络编程的基础- (1)套接字地址结构 大多说套接字函数都需要一个指向套接字地址结构的指针作为参数,每个协议族都定义它自己的套接字地址结构,这些结构都以sockadd_开头. IPV4套接字地址结构 IPv4套接字地址结构通常称为"网际套接字地址结构",以sockaddr_in命名,并定义在 /* Internet address. */ typedef

第三章-套接字编程

套接字结构一般从内核到进程.从进程到内核,其中从内核到进程是值-结果参数的例子 地址转换函数推荐使用inet_ntop,inet_pton适用于ipv4跟ipv6 套接字地址结构 struct sockaddr_in{ uint8_t sin_len;//长度 posix规范不需要这个 sa_family_t sin_family; //协议族,无符号短整数.一般表示AF_INET in_port_t  sin_port;//端口 struct in_addr sin_addr;//32位ip地

UNIX网络编程第3章套接字编程简介3.2套接字地址结构3.3值结果参数3.4字节排序函数

1: #include <iostream> 2: #include "../lib/unpsunyj.h" 3: 4: int main(int argc, char **argv) 5: { 6: union { 7: short s; 8: char c[sizeof(short)]; 9: } un; 10:   11: un.s = 0x0103; 12: std::cout << "un.s =: " << un.s

Shell学习笔记——第三章

第三章 /etc/passwd 文件包含一个所有系统用户账户组成的列表,以及一些关于每个用户的基本信息. 例rich:x:501:Rich Blum:/home/rich:/bin/bash 每个条目都有7个数据字段,例使用冒号分隔.系统使用这些字段中的数据向用户分配具体的特性.这些字段分别有 用户名:用户密码(如果密码存储在其他文件中,则为占位符):用户的系统用户ID编号:用户的系统组的ID编号:用户的全名:用户默认的主目录:用户的默认Shell目录: cd 命令 略过 列表命令(ls) 参数

《网络编程》套接字编程简介

本节介绍的套接字是可以实现不同计算机之间的远程进程间通信.套接口是网络进程的 ID,在网络中每一个节点都有一个网络地址,也就是 IP 地址,两个进程间通信时,首先要确定各自所在网络节点的网络地址.但是,网络地址只要确定进程所在的计算机,由于一台计算机上同时可能有多个网络进程,所以仅凭网络地址还不能确定是网络中的哪一个进程,因此套接口中还需要其他信息,也就是端口.在一台计算机中,一个端口号只能分配给一个进程,所以,进程和端口之间是一一对应的关系.因此,使用端口号和网络地址的组合就能唯一地确定整个网

【Unix网络编程】chapter3 套接字编程简介

chapter3套接字编程简介3.1 概述 地址转换函数在地址的文本表达和他们存放在套接字地址结构中的二进制值之间进行转换.多数现存的IPv4代码使用inet_addr和inet_ntoa这两个函数,不过这两个新函数inet_pton和inet_ntop同时适用于IPv4和IPv6. 3.2 套接字地址结构 sockaddr_ 3.2.1 IPv4套接字地址结构 IPv4套接字地址结构通常也称为"网际套接字地址结构",它以sockaddr_in命令,定义在<netinet/in.

UNP学习笔记(第二章:传输层)

本章的焦点是传输层,包括TCP.UDP和SCTP. 绝大多数客户/服务器网络应用使用TCP或UDP.SCTP是一个较新的协议. UDP是一个简单的.不可靠的数据报协议.而TCP是一个复杂.可靠的字节流协议. 这里重点放在TCP中. 用户数据报协议(UNP) 应用程序往UDP套接字写入一个消息,该消息随后被封装到一个UDP数据报,该UDP数据报进而又被封装到一个IP数据报,然后发送到目的地(面向非连接的). UDP不保证UDP数据报会达到最终目的地,不保证各个数据报的先后顺序跨网路后保持不变,也不

Java学习笔记—第三章

第三章  标识符.关键字和数据类型 1. Java标识符和关键字:在程序设计中,通常用一个记号对变量.常量.方法和类等进行标识,这个记号称为标识符.Java语言本身使用了一些标识符,这些标识符称为Java关键字,用户在命名标识符时应该避免使用这些Java关键字,否则将导致程序无法进行编译. Java中的关键字如下: abstract 抽象 assert 断言 boolean 布尔 break 中断 byte 字节 catch 捕获 char 字符 class 类 continue 继续 defa

【PMP】Head First PMP 学习笔记 第三章 过程框架

第三章 过程框架 项目中完成的所有工作都由过程构成. 项目中的完成的所有工作都有一个模式(pattern).先计划,再去做.工作时,总是对项目与原先的计划进行比较.如果开始偏离计划,就要由你做出矫正,让一切重新走上正轨.过程框架--过程租和知识领域--正式这一切顺利完成的关键. 分阶段管理 分阶段,项目的每个阶段(phase)都会经过5个过程租,从启动到收尾,项目的多个阶段就会存在各种关联关系 顺序关系(sequenital relationship).多个阶段相继发生并不存在重叠,每个阶段在前