APUE 学习笔记(十一) 网络IPC:套接字
1. 网络IPC
/* 创建一个套接字 */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
#include <sys/socket.h>
int shutdown(int sockfd, int how);
2. 套接字地址
#include <arpa/inet.h> uint32_t htonl(uint32_t hostint32); // 返回值:以网络字节序表示的32位整型数
uint16_t htons(uint16_t hostint16); // 返回值:以网络字节序表示的16位整型数
uint32_t ntohl(uint32_t netint32); // 返回值:以主机字节序表示的32位整型数
uint16_t ntohl(uint16_t netint16); // 返回值:以主机字节序表示的16位整型数
struct sockaddr {
sa_family_t sa_family; /* address family */
char sa_data[]; /* variable-length address */
};
在IPv4 套接字地址结构 sockaddr_in (in表示internet网络):
struct in_addr {
in_addr_in s_addr; /* IPv4 address*/
}; struct sockaddr_in {
sa_family_t sin_family; /* address family */
in_port_t sin_port; /* port number */
struct in_addr sin_addr; /* IPv4 address */
unsigned char sin_zero[];
};
二进制地址格式和 点分十进制格式转换:
#include <arpa/inet.h> const char* inet_ntop(int domain, const char* addr, char* str, socklen_t size);
int inet_pton(int domain, const char* str, void* str);
#include <sys/socket.h>
#include <netdb.h> int getaddrinfo(const char* host, const char* service, const struct addrinfo* hint, struct addrinfo* res);
void freeaddrinfo(struct addrinfo* ai);
struct addrinfo {
int ai_flags; /* customize behavior */
int ai_family; /* address family */
int ai_socktype; /* socket type */
int ai_protocol; /* protocol */
socklen_t ai_addrlen; /* length in bytes of address */
struct sockaddr* ai_addr; /* address */
char* ai_canonname;
struct addrinfo* ai_next; /* next in list */
....
};
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdio.h> void print_family(struct addrinfo* aip)
{
fprintf(stdout, "family:");
switch (aip->ai_family) {
case AF_INET:
fprintf(stdout, "inet");
break;
case AF_INET6:
fprintf(stdout, "inet6");
break;
case AF_UNIX:
fprintf(stdout, "unix");
break;
case AF_UNSPEC:
fprintf(stdout, "unspecfied");
break;
default:
fprintf(stdout, "unknown");
}
} void print_type(struct addrinfo* aip)
{
fprintf(stdout, "type");
switch (aip->ai_socktype) {
case SOCK_STREAM:
fprintf(stdout, "stream");
break;
case SOCK_DGRAM:
fprintf(stdout, "datagram");
break;
case SOCK_SEQPACKET:
fprintf(stdout, "seqpacket");
break;
case SOCK_RAW:
fprintf(stdout, "raw");
break;
default:
fprintf(stdout, "unknown (%d)", aip->ai_socktype);
}
} void print_protocol(struct addrinfo* aip)
{
fprintf(stdout, "protocol");
switch (aip->ai_protocol) {
case :
fprintf(stdout, "default");
break;
case IPPROTO_TCP:
fprintf(stdout, "tcp");
break;
case IPPROTO_UDP:
fprintf(stdout, "udp");
break;
case IPPROTO_RAW:
fprintf(stdout, "raw");
break;
default:
fprintf(stdout, "unknown (%d)", aip->ai_protocol);
}
} void print_flags(struct addrinfo* aip)
{
fprintf(stdout, "flags");
if (aip->ai_flags == ) {
fprintf(stdout, "");
} else {
if (aip->ai_flags & AI_PASSIVE) {
fprintf(stdout, "passive");
}
if (aip->ai_flags & AI_CANONNAME) {
fprintf(stdout, "canon");
}
if (aip->ai_flags & AI_NUMERICHOST) {
fprintf(stdout, "numhost");
}
}
}
int main(int argc, char* argv[])
{
struct addrinfo* ailist = NULL;
struct addrinfo* aip = NULL;
struct addrinfo hint;
struct sockaddr_in* sinp;
const char* addr = NULL;
char abuf[INET_ADDRSTRLEN]; if (argc != ) {
fprintf(stdout, "usage:%s <hostname> <service>", argv[]);
return ;
} hint.ai_flags = AI_CANONNAME;
hint.ai_family = ;
hint.ai_socktype = ;
hint.ai_protocol = ;
hint.ai_addrlen = ;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
int ret = getaddrinfo(argv[], argv[], &hint, &ailist);
if (ret != ) {
fprintf(stderr, "getaddrinfo error\n");
return ;
} for (aip = ailist; aip != NULL; aip = aip->ai_next) {
print_flags(aip);
print_family(aip);
print_type(aip);
print_protocol(aip);
fprintf(stdout, "\n\thost %s", aip->ai_canonname ? aip->ai_canonname : '-');
if (aip->ai_family == AF_INET) {
sinp = (struct sockaddr_in*)aip->ai_addr;
addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
fprintf(stdout, "address %s", addr ? addr : "unknown");
fprintf(stdout, "port %d", ntohs(sinp->sin_port));
}
fprintf(stdout, "\n");
}
return ;
}
套接字与地址绑定:
#include <sys/socket.h> int bind(int sockfd, const struct sockaddr* addr, socklen_t len);
3. 建立连接
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr* addr, socklen_t len);
#include <sys/socket.h>
#define MAXSLEEP 128 int connect_retry(int sockfd, const struct sockaddr* addr, socklen_t len)
{
/* try to connect with exponential backoff */
for (int nsec = ; nsec <= MAXSLEEP; nsec << 1) {
if (connect(sockfd, addr, len) == ) {
/* connection accepted */
return ;
} /* delay before trying again */
if (nsec <= MAXSLEEP / )
sleep(nsec);
}
return -;
}
#include <sys/socket.h> int listen(int sockfd, int backlog);
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr* addr, socklen_t* len);
4. 数据传输
#include <sys/socket.h> ssize_t send(int sockfd, const void* buf, size_t bytes, int flags); // 等同于 write,套接字必须已连接
ssize_t sendto(int sockfd, const void* buf, size_t bytes, int flags, const struct sockaddr* dstaddr, socklen_t dstlen);
#include <sys/socket.h> ssize_t recv(int sockfd, void* buf, size_t bytes, int flags); //类似于 read
ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* addr, socklen_t* addrlen);
/* tcp_connect for client:
* hostname or ip: www.google.com or 127.0.0.1
* service or port: http or 9877
*/
int tcp_connect(const char* hostname, const char* service)
{
struct addrinfo hints;
struct addrinfo* result;
struct addrinfo* rp; memset(&hints, , sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; int res = getaddrinfo(hostname, service, &hints, &result);
if (res != ) {
fprintf(stderr, "tcp_connect error for %s, %s: %s", hostname, service, gai_strerror(res));
exit();
} int sockfd;
for (rp = result; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd < )
continue;
int rc = connect(sockfd, rp->ai_addr, rp->ai_addrlen);
if (rc == )
break;
close(sockfd);
}
if (rp == NULL) {
unix_error("tcp_connect error");
}
freeaddrinfo(result);
return sockfd;
}
/* tcp_listen for server:
* hostname or ip: www.google.com or 127.0.0.1
* service or port: http or 9877
*/ int tcp_listen(const char* hostname, const char* service, socklen_t* paddrlen)
{
struct addrinfo hints;
struct addrinfo* result;
struct addrinfo* rp; memset(&hints, , sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; int res = getaddrinfo(hostname, service, &hints, &result);
if (res != ) {
fprintf(stderr, "tcp_listen error for %s, %s: %s", hostname, service, gai_strerror(res));
exit();
} int listenfd;
for (rp = result; rp != NULL; rp = rp->ai_next) {
listenfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (listenfd < )
continue;
int rc = bind(listenfd, rp->ai_addr, rp->ai_addrlen);
if (rc == )
break;
Close(listenfd);
}
if (rp == NULL) {
unix_error("tcp_listen error");
}
Listen(listenfd, LISTENQ);
if (paddrlen) {
*paddrlen = rp->ai_addrlen;
}
freeaddrinfo(result);
return listenfd;
}
5. 套接字选项
#include <sys/socket.h> int setsockopt(int sockfd, int level, int option, const void* val, socklen_t len);
int getsockopt(int sockfd, int level, int option, void* val, socklen_t lenp);
6. 带外数据
7. 非阻塞I/O
APUE 学习笔记(十一) 网络IPC:套接字的更多相关文章
- UNP学习笔记3——基本UDP套接字编程
1 概述 TCP和UDP网络编程存在一些本质的差异,主要是由于传输层的差别:UDP是无连接的不可靠的数据报协议,而TCP是面向连接的字节流协议. 下图是典型的UDP客户端和服务器之间的通信流程.客户不 ...
- Unix环境高级编程(十七)网络IPC套接字
通过网络套接字可以使得不同计算机上运行的进程相互通信. 1.创建套接字 #include <sys/socket.h> Int socket( int domain, int type, ...
- 孙鑫MFC学习笔记16:异步套接字
16 1.事件对象 2.CreateEvent创建事件对象 3.SetEvent设置事件对象为通知状态 4.ResetEvent设置事件对象为非通知状态 5.InitializeCriticalSec ...
- UNP学习笔记1——基本TCP套接字编程
1 套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数.每个协议族都定义了自己的套接字结构.这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾. 1.1 I ...
- 第十六章:网络IPC 套接字
一.IP地址和端口 套接字接口可以用于计算机间通信.目前计算机间使用套接字通讯需要保证处于同一网段. 为了查看是否处于同一网段,我们可以使用IP地址判断. IP地址是计算机在网络中的唯一标识.IP地址 ...
- python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容
python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容 Beautiful Soup 是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖 ...
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
- python3.4学习笔记(十一) 列表、数组实例
python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...
- Go语言学习笔记十一: 切片(slice)
Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...
随机推荐
- 《毛毛虫团队》第八次团队作业:ALPHA冲刺
一:实验名称:软件测试与ALPHA冲刺 二:实验目的与要求 (1)掌握软件测试基础技术. (2)学习迭代式增量软件开发过程(Scrum). 三:实验步骤 任务一:各个成员今日完成的任务: 任务二:明日 ...
- Js笔记 14
<script> // <!-- 课 对象 // //对象的创建方法 // 1.var obj = {} plainobject 对象字面量 对象直接量 // 2.构造函数 ...
- 从输入URL到页面加载完成的过程中都发生了什么事情?
为了便于理解,我将整个过程分为了六个问题来展开. 第一个问题:从输入 URL 到浏览器接收的过程中发生了什么事情? 从触屏到 CPU 首先是「输入 URL」,大部分人的第一反应会是键盘,不过为了与时俱 ...
- vue 前端判断输入框不能输入0 空格。特殊符号。
oninput="value=value.replace(/[^\d.]/g,'').replace(/\.{2,}/g,'.').replace('.','$#$').replace(/\ ...
- 洛谷 P2735 电网
https://www.luogu.org/problemnew/show/P2735 定理什么的最讨厌了,匹克定理?不会,也不想学. 粉色的为电网,将图中的电网我们将他构造一个矩形,然后蓝色和绿色的 ...
- Java中的==和equals的区别详解
1.基础知识 (1)String x = "hello"; (2)String x = new String ("hello"); 第1种方式的工作机制是,首先 ...
- 常用的windows小工具指令和如何打开自定义的程序
windows可以通过 开始->运行->输入程序名 或 windows键+R键 两种方式来启动windows中自带的程序或手动安装的程序.下面介绍一些常用的windows工具的指令和如何打 ...
- 代理工具--fiddle
正则匹配 1)前缀为“EXACT:”表示完全匹配:只有match=rules时,才匹配 2)无前缀表示基本搜索,表示搜索到字符串就匹配:只要match中包含了rules的字符串,即可 3)前缀为“NO ...
- 第7课 Thinkphp 5 模板输出变量使用函数 Thinkphp5商城第四季
目录 1. 手册地址: 2. 如果前面输出的变量在后面定义的函数的第一个参数,则可以直接使用 3. 还可以支持多个函数过滤,多个函数之间用"|"分割即可,例如: 4. 变量输出使用 ...
- Python爬取全站妹子图片,差点硬盘走火了!
在这严寒的冬日,为了点燃我们的热情,今天小编可是给大家带来了偷偷收藏了很久的好东西.大家要注意点哈,我第一次使用的时候,大意导致差点坏了大事哈! 1.所需库安装 2.网站分析 首先打开妹子图的官网(m ...