本章开始讲解套接字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[];
};

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

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

通用的套接字地址结构

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

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

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

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

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[];
};

字节排序函数

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

下面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实现代码

 #include "unp.h"
ssize_t readn(int fd,void *vptr,size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr; ptr = vptr;
nleft = n;
while(nleft > )
{
if((nread = read(fd,ptr,nleft)) < )
{
if(errno == EINTR)
{
nread = ;
}
else
{
return -;
}
}
else if(nread == )
{
break;
}
nleft -= nread;
ptr += nread;
}
return (n-nleft);
}

writen实现代码

 #include "unp.h"
ssize_t written(int fd,void *vptr,size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while(nlfet > )
{
if((nwritten = writen(fd,ptr,nleft)) <= )
{
if(nwritten < && errno ==EINTR)
{
nwritten =;
}
else
{
return -;
}
} nleft -= nwritten;
ptr += nwritten;
}
return n;
}

readline实现代码

 #include "unp.h"
ssize_t readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n,rc;
char c,*ptr; ptr = vptr;
for(n = ; n < maxlen; n++)
{
if( (rc = read(fd, &c)) == )
{
*ptr ++ = c;
if(c == '\n')
break;
}
else if (r c== )
{
*ptr = ;
return (n-);
}else
return (-);
} *ptr = ;
return (n);
}

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

  1. UNP学习笔记3——基本UDP套接字编程

    1 概述 TCP和UDP网络编程存在一些本质的差异,主要是由于传输层的差别:UDP是无连接的不可靠的数据报协议,而TCP是面向连接的字节流协议. 下图是典型的UDP客户端和服务器之间的通信流程.客户不 ...

  2. UNP学习笔记1——基本TCP套接字编程

    1 套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数.每个协议族都定义了自己的套接字结构.这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾. 1.1 I ...

  3. UNIX网络编程 第3章 套接字编程简介

    套接字结构类型和相关的格式转换函数

  4. 《DOM Scripting》学习笔记-——第三章 DOM

    <Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...

  5. The Road to learn React书籍学习笔记(第三章)

    The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...

  6. [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设

    [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设 敲黑板!! <q>元素添加短引用,<blockquote>添加长引用 在段落里添加引用就使用< ...

  7. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

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

    chapter3套接字编程简介3.1 概述 地址转换函数在地址的文本表达和他们存放在套接字地址结构中的二进制值之间进行转换.多数现存的IPv4代码使用inet_addr和inet_ntoa这两个函数, ...

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

    chapter3套接字编程简介3.1 概述 地址转换函数在地址的文本表达和他们存放在套接字地址结构中的二进制值之间进行转换.多数现存的IPv4代码使用inet_addr和inet_ntoa这两个函数, ...

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

    本章的焦点是传输层,包括TCP.UDP和SCTP. 绝大多数客户/服务器网络应用使用TCP或UDP.SCTP是一个较新的协议. UDP是一个简单的.不可靠的数据报协议.而TCP是一个复杂.可靠的字节流 ...

随机推荐

  1. docker (centOS 7) 使用笔记3 - docker swarm mode

    1. 什么是docker swarm mode docker engine自带的 容器管理 工具.功能比较早的 docker swarm 更多,且集成在docker engine里. (docker ...

  2. g2o初始化一些

    今天看了一下智能指针的东西,发现更简单的思路: 就是Block和solver构造时,需要传递unique_ptr,那我们将普通指针转换成unique_ptr不就可以了么: // 初始化g2o //第一 ...

  3. Codeforces Round #240 (Div. 2) B 好题

    B. Mashmokh and Tokens time limit per test 1 second memory limit per test 256 megabytes input standa ...

  4. springboot 2.0配置集成thymeleaf的坑

    Servlet.service() for servlet [dispatcherServlet] in context with path [] java.lang.NoClassDefFoundE ...

  5. 【转】手摸手,带你用vue撸后台 系列三(实战篇)

    前言 在前面两篇文章中已经把基础工作环境构建完成,也已经把后台核心的登录和权限完成了,现在手摸手,一起进入实操. Element 去年十月份开始用vue做管理后台的时候毫不犹豫的就选择了Elemen, ...

  6. iOS 关于请求参数在cookie里面

    一.首先了解一下什么cookie cookie是在客户端存储服务器状态的一种机制.web服务器可以通过set-cookie或者set-cookie2 HTTP头部设置cookie. Cookie可以分 ...

  7. bzoj 1396 识别子串 后缀树+线段树

    题目大意 给定一个长度\(\le100000\)的字符串 求每一个位置的最短识别子串 对于位置\(x\),能识别子串\(s[i...j]\)的条件是 1.\(i\le x \le j\) 2.\(s[ ...

  8. [LeetCode] Path Sum II 深度搜索

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  9. django+vue+nginx生产环境部署配置

    部署环境: 1. linux redhat 7.1 2.python 3.6.3 3. vue 4. nginx 5. gunicorn 6. supervisord 安装: 一. 基础环境安装 1. ...

  10. C语言字符串操作总结大全(超详细)【转】

    转自:http://www.jb51.net/article/37410.htm )字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strc ...