UNIX网络编程之基础

UNIX环境高级编程、UNIX网络编程(卷一)环境搭建 最近学习这两本书,在直接编译书本源程序时,出现头文件“apue.h”(UNIX环境高级编程)及“unp.h”(UNIX网络编程)错误,在这里坐下配置的笔记。 首先需要安装Linux系统。(在VirtualBox虚拟机里安装Centos6.7的Linux系统) APUE: 1、使用浏览器从http://www.apuebook.com/code3e.html下载源码src.3e.tar.gz( 阅读详情

前言

因为socket编程中涉及到的结构比较多,因此在此做了一些记录,方便后续的查阅。


1. 结构体相关

1)sockaddr和sockaddr_in详解

sockaddr在很早的版本使用,其中成员sa_data把通信的IP地址和端口混合在一起,结构体和头文件见如下:

#include <sys/socket.h>

struct sockaddr {
	sa_family_t 				sin_family;
	char 						sa_data[14];	
}

sockaddr_in将早期的结构的ip和端口分离出来,结构如下:

#include <netinet/in.h>
#include <arpa/inet.h>

struct sockaddr_in
{
	sa_family_t 				sin_family;
	uint16_t 					sin_port;
	struct in_addr				sin_addr;
	char						sin_zero[8];
};
struct in_addr
{
	in_addr_t					s_addr;
};

sin_port和sin_addr都必须是网络字节序(大端字节序),而我们通常使用的linux等是小端字节序(主机字节序),因此需要使用接口转换。

2) 字节序转换的函数

~~inet_addr~~如今已废除,参考<<UNIX网络编程卷1>>3.6节P68,替代的有inet_addr,更好的替代是inet_pton(支持IPv4和IPv6)

#include <arpa/inet.h>
/*返回:若字符串有效则为1,否则为0/*/
int inet_aton(const char *strptr, struct in_addr *addrptr);
/*返回:若字符串有效则为32位二进制网络字节序的IPv4地址,否则为INADDR_NONE*/
in_addr_t inet_addr(const char *strptr);
/*返回:指向一个点分十进制数串的指针*/
char *inet_ntoa(struct in_addr inaddr); 

/*返回:若成功则为1,若输入不是有效的表达式则为0, 若出错则为-1*/
int  inet_pton(int family, const char *strptr, void *addrptr/*&foo.sin_addr*/);
/*如成功则为指向结果的指针,若出错则为NULL*/
len:如果是IPv4,填写16,在<netinet/in.h>中有定义宏 
#define INET_ADDRSTRLEN 16 
#define INET6_ADDRSTRLEN 46
char str[INET_ADDRSTRLEN];
ptr = inet_ntop(AF_INET, &foo.sin_addr, str, sizeof(str));
const char *inet_ntop(int family, const void *addrptr,  char *strptr, size_t len);

e.g:

struct sockaddr_in servaddr;
servaddr.sin_port = htons(13);
servaddr.sin_addr.s_addr = inet_addr("192.168.1.1");
//尽量使用如下,因为该接口不仅支持IPV4还支持IPV6

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int  inet_pton(int af, const char *src, void *dst); //将"点分十进制"->"二进制整数”
//struct  in_addr s;
char *ip = "192.168.1.1";
inet_pton(AF_INET, (void*) ip,  (void*)&s);

注意: 如果端口是0()或INADDR_ANY(值通常为0), 可以不转为网络字节序(NBO),因为使用htonl并非必要,不过头文件<netinet/in.h>中定义了所有INADDR_按照主机字节序定义,我们还是要习惯使用htonl转<<UNIX网络编程卷1>>4.4节P83。
推荐使用inet_pton,支持IPV4和IPV6,只做小小的改动,但仅修改一点点,
其他地方都需要修改,因此更好的做法是编写协议无关的程序(11-11,使用了getaddrinfo函数)

struct sockaddr_in ->struct sockaddr_in6
socket(AF_INET, SOCK_STREAM,0) 	-> socket(AF_INET6, SOCK_STREAM, 0);
servaddr.sin_family = AF_INET	->	servaddr.sin6_family = AF_INET6;
servaddr.sin_port 				->		servaddr_sin6_port
inet_pton(AF_INET,...,...)		->		inet_pton(AF_INET6,...,...);

#include	"unp.h"

int
main(int argc, char **argv)
{
	int					sockfd, n, counter = 0;
	char				recvline[MAXLINE + 1];
	struct sockaddr_in	servaddr;

	if (argc != 2)
		err_quit("usage: a.out <IPaddress>");

	if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		err_sys("socket error");

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;	/*协议族成员设置为AF_INET*/
	servaddr.sin_port   = htons(13);	/* daytime server */
	if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
		err_quit("inet_pton error for %s", argv[1]);

	if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
		err_sys("connect error");

	while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
		counter++;
		recvline[n] = 0;	/* null terminate */
		if (fputs(recvline, stdout) == EOF)
			err_sys("fputs error");
	}
	if (n < 0)
		err_sys("read error");

	printf("counter = %d\n", counter);
	exit(0);
}

3)问题和结论

3-1)编写协议无关的代码,支持IPv4和IPv6

3-2) 使用域名替代点分十进制的方式


2. API相关

1)connect函数

#include <sys/socket.h>
/*返回: 若成功则为0,若出错则为-1*/
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

如果是TCP套接字,connect激发TCP的三次握手过程,仅再链接成功或出错返回,出错有如下几种情况:

  • 客户端发送SYN分节,没有收到服务端的响应,返回ETIMEDOUT错误,后续会间隔时间继续发送SYN。
  • 若对客户的SYN响应是RST(表示复位),表明服务器在客户端指定的端口无进程运行,这是一种硬错,客户一接收到RST就马上返回ECONNREFUSED错误。
    客户端运行,服务端不运行
root@ubuntu:/opt/socket/unpv13e/intro# ./daytimetcpcli 127.0.0.1
connect error: Connection refused

抓包:
在这里插入图片描述

  • 若客户发出SYN分节路由器转发ICMP错误, 认为是软错误(soft error),客户主机内核保存该消息,按照时间间隔继续发送,如果再持续一段时间(75s)任然没有收到响应, ICMP错误(EHOSTUNREACH或ENETUNREACH)返回给客户端。

2)bind函数

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr * myaddr, socklen_t addrlen);//返回0成功,-1出错
  • 客户端一般不调用bing,即使用通配地址(INADDR_ANY)和端口0(内核自行分配端口)IP地址和端口内核选择;
  • 服务端一般会指定端口, IPv4地址使用通配地址(INADDR_ANY,其值一般为0),如果服务器没有把IP地址绑到它的套接字上,内核就把客户发送的SYN的目的IP地址作为服务器的源IP地址,如果是IPv6,参考4.4节的方式处理。

在这里插入图片描述

  • 如果让内核来为套接字选择临时端口,想获取分配的端口,需要调用getsockname来返回协议地址。通常指定服务器的端口应该在(5000, 49152)范围,避免与临时端口号(一般大于49152或小于5000 P98详)

  • 从bind函数返回的一个常见错误是EADDRINUSE(地址已被使用)。解决方式使用套接字选项SO_REUSEADDR/SO_REUSEPORT来解决,参考7.5节讨论。

后续开专题记录,这里仅做一个目录性的引导,后续在此链接。

3)listen函数

#include <sys/socket.h>
int listen(int sockfd, int backlog);//成功返回0, 出错返回-1

4)accept函数

#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);//成功非负描述符,出错-1

3. 难点

后续开专题记录,这里仅做后续的链接。

未完待续…

UNIX网络编程实战源码详解 UNIX网络编程是计算机网络领域中的一项重要技能,它允许开发者利用UNIX系统提供的网络接口进行编程,实现数据的网络传输和进程间的通信。该领域的核心是套接字(Socket)编程,它提供了一种在不同操作系统和平台间交换数据的通用方式。本章将概述UNIX网络编程的基础,包括其发展背景、核心概念以及在网络时代中的重要性,为深入理解后续章节打下坚实的基础。套接口(Socket)是计算机网络通信的基本构件,其功能类似于现实世界中的电话插孔,它是应用程序进行网络通信的一种抽象。 阅读详情

相关推荐

Linux网络编程基础(详细)

讲述linux网络的原理、命令,以及关于TCP/UDP、sokect编程

linux/unix网络编程-入门基础

一、套接字   在网络中用来描述计算机中不同程序与其他计算机程序通信的方式。为了区分不同应用程序的进程和连接,需要使用应用程序与TCP/IP协议交互的套接字端口。   主要用到三个参数:通信的目的IP地址、使用的传输协议(TCP或UDP)和使用的端口号。 1.套接字相关的数据类型   套接字编程是,通常使用sockaddr和sockaddr_in这两个系统中定义的数据类型结构体。 struct s...

对自己笑 765

《深入浅出图神经网络:GNN原理解析》学习笔记

期末考完了,该上道了 目录一、图的概述1.基本概念2.图的存储和遍历3.应用分类二、神经网络基础1.机器学习2.神经网络三、卷积神经网络(CNN)1.卷积与池化2.卷积神经网络四、表示学习1.意义2.自编码器五、图信号处理与图卷积神经网络1.矩阵计算前置知识2.图信号与图的拉普拉斯矩阵3.图傅里叶变换4.图滤波器(Graph Filter)5.图卷积神经网络(GCN) 一、图的概述 1.基本概念 1.顶点(Vertex)表示研究的对象,边(Edge)表示两个对象之间特定的研究关系 2.图为顶点和边的集合.

且视他人之疑目如盏盏鬼火,大胆地去走你的夜路 2045

Unix网络编程学习笔记

unix网络编程,C语言,多线程,多进程,epoll,select

weixin_45045804的博客 2629

win10离线安装.NetFrameWork3.5出现0x800F081F解决办法。

由于公司开发环境是内网,并且安装arcgis10.2又需要.NetFrameWork3.5的环境,安装.NetFrameWork3.5的又总是报错“0x800F081F”找不到源文件。折腾了两天总算解决了。 首先我们能在网上搜索到的教程,你一定看到过这样的教程,就是使用下面的命令来进行安装。 dism /online /Enable-Feature /Featu...

AIGIS的博客 1万+

Vue 实现华视身份证读卡器功能

在www.downcc.com下载“华视cvr100驱动”安装程序; 华视电子官网有相应的文档说明和程序下载 一、服务安装 选择安装目录: 启动读卡服务: 安装成功会有如图所示: 注意事项: 安装开发包必须使用管理员权限,因为windows服务和读卡器设备驱动程序均需要管理员权限,否则会安装失败。 win10需要修改组策略才有管理员权限。 二、服务的使用 打开浏览器,输入地址http://127.0.0.1:19196/mainpage,回车 点击openDevice: 点.

zyqgt960812的博客 6501

Unix网络编程第一卷学习总结

简述和TCP/IP 如果要写一个简单的ipv6客户端程序,需要sockaddr_in6地址,其余用法和ipv4的用法一致, 先指定地址族,端口,ip地址,connect成功后,就可以发包收包

quinta2008,阳光风雨就是我 1874

MinIO vs 华为云OBS:成本、性能与兼容性深度对比(含实测数据)

本文深度对比了开源对象存储MinIO与华为云OBS在成本、性能、兼容性及运维方面的核心差异。通过实测数据与全生命周期成本分析,为技术决策者提供选型依据。文章指出,MinIO在长期成本控制、性能深度优化及S3 API兼容性方面优势显著,而华为云OBS则提供开箱即用的便利性。

kmeans3miner的博客 593

UNIX网络编程

UNIX网络编程

weixin_45516025的博客 1595

实现飞书机器人推送消息到指定群组或者用户

飞书是一个集成了聊天、协作和办公功能的企业级平台,广泛应用于企业内部沟通和协作。飞书机器人(Feishu Bot)是一种强大的工具,允许开发者通过编程接口与飞书进行互动,从而实现自动化消息推送和任务管理。本文将详细介绍如何通过飞书机器人推送消息给指定的人或者群组,帮助您快速上手。

qq_41898196的博客 5863

告别编译臃肿!手把手教你为Arduino UNO打造超轻量级U8g2中文字库(附完整工具链)

本文详细介绍了如何为Arduino UNO打造超轻量级U8g2中文字库,解决默认字库占用大量存储空间的问题。通过自定义字体工具链,提取项目所需汉字并生成精简字库,显著减少程序体积。文章包含完整实现步骤、优化技巧及实战经验,帮助开发者在资源受限的微控制器上高效显示中文。

weixin_29274337的博客 256

unix网络编程——网络基础

网络编程基础

weixin_46199479的博客 1239

YOLOv8 交通管理三大核心功能 —— 二、违章检测系统 详细解释及代码完整示例

YOLOv8交通违章检测系统

u010117029的博客 500

UNIX 网络编程

目录 1 socket网络编程步骤 1.1 服务器编程步骤 1.2 客户端编程步骤 1.3 函数以及结构解释 2 基于TCP的一对多网络编程 2.1 服务器编程步骤 2.2 客户端编程 2.3 函数解释 2.4 基于TCP的网络聊天室 3 基于UDP的一对多编程 3.1 服务器编程步骤 3.2 客户端编程步骤 3.3 UDP下的读写数据 3.4 函数解释 3.5 基于...

qq_39545674的博客 3391

Cesium 入门

Viewer:主要窗口Cesium 展示三维要素内容的主要窗口,包含三维地球的视窗,还包含了一些基础控价const viewer = new Cesium.Viewer('div的ID',{ options可选参数 },包括图层)options可选参数animation: false, 隐藏动画效果timeline:false, 隐藏时间轴等等Scene:场景类,隐藏地球图层Entity:实体类。

虎康的博客 3665

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

UNIX网络编程初入

UNIX网络编程初入

m0_54786792的博客 468

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

《UNIX网络编程》01

《UNIX网络编程》01 《UNIX网络编程》环境搭建,实现第一个程序。 新的开始 《UNIX》网络编程要运行这里的程序需要搭建开发环境。 1.系统选择:centos7 虚拟机 2.下载源码:www.unpbook.com。 按照图片顺序下载: 下载zip文件,不用担心解压问题 选择保存文件,保存的文件在“主目录——下载”文件夹里。 3.提取源码:选中文件 “双击或者回车”,然后点击“提取”。 会让你选择提取路径,我选择了“主目录”,然后在点击“提取”,就可以在主目录下看到提取出来的全

qq_27699113的博客 594

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

《 UNIX网络编程》源码的使用

关于 最近在学网络编程,借了一本书《UNIX网络编程 第一卷:套接口API (第3版)》 STEVENS大神著的! 学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google unpv13e.tar.gz 并在网络上找到了:源码:http://code.google.com/p/stid/downloads/detail?name=unpv13e.tar.gz&can=2&q= 现在就是使用的问题了! 关于在

sebeefe的博客 283

【总结】【Unix网络编程】前言及基础知识

序言及基本知识刚刚买到《Unix网络编程》的时候,舍友们都被它的厚度吓到了,都说读这种又厚又专业的书简直煎熬,何况咱们还不是计算机专业的!但俗话说得好——大力粗奇迹嘛(脑补语气),干脆大力的去读肯定有收获!于是两个星期过去了进度过三成了。这本书好,真好,虽然厚但是易读易懂就是好。秉着做笔记的态度写日记的文笔,我将逐步将看过的内容进行分析总结,也希望这一系列文章能够解除一些读者对网络对编程的恐惧,更加

甭管多不多反正写了! 2014

UNIX网络编程卷1和2资源推荐:深入学习UNIX网络编程的必备宝典

UNIX网络编程卷1和2资源推荐:深入学习UNIX网络编程的必备宝典 【下载地址】UNIX网络编程卷1和2资源下载 UNIX网络编程卷1和2资源下载本仓库提供UNIX网络编程卷1和卷2的资源文件下载,包含以下两本书籍:1. **UNIX网络编程卷1:套接字联网API(第3版).pdf**2. **UNIX网络编程_卷2_...

gitblog_09790的博客 704

unix网络编程

略

google20的博客 673

UNIX网络编程源码的使用

关于 最近在学网络编程,借了一本书《UNIX网络编程 第一卷:套接口API (第3版)》 STEVENS大神著的! 学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google

Our little drops... 1868
上一篇: unpv13e在arm上编译
下一篇: tcpdump基本使用和实战分析
帘下有白绿
博客等级 码龄12年 165粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值