unix network programming(3rd)Vol.1 [第1章]《读书笔记系列》
文章最开头介绍了
-
获取时间的C/S 模型的代码, 还用了实现了IPV6的版本
-
unix 介绍了errno值,以及在多进程/多线程中的问题
多线程中不用全局errno,而是用返回值 处理error 详细见第26章
//可以这么写 int n; if( (n=pthread_mutex_lock(&ndone_mutex)) !=0 ) errno=n,err_sys("ptherad_mutex_lock error");// 逗号分割,不用{} 花括号 //当然我们也可以封装下 void warpper_Pthread_mutex_lock(pthread_mutex *mptr) { int n; if( (n=pthread_mutex_lock(mptr) ) == 0 ) return; errno = n; err_sys("ptherad_mutex_lock error"); }
-
简单介绍了,buffer溢出老问题,基本上也都是c99/c11/c++11替换老版本
windows 是 _s系列 比如strcpy_s, memcpy_s, sprintf_s
当然wide strings版本也有封装 wsprinf_s,wmemcpy_s
linux 的wide strings头文件是(wchar.h) printf() -> puts() Write string to stdout
gets() -> fgets()
sprintf() -> snprintf()
strcat()-> strncat()->strlcat()//最好用strlcat
strcpy()-> strncpy()->strlcpy()//最好用strlcpy等等
《Strlcpy和strlcat——一致的、安全的字符串拷贝和串接函数 》详细介绍了为什么 英文原版
中文版
size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char *dst, const char *src, size_t size);
简单概括: strcat、strcpy 容易溢出, strncat、strncpy() 最后一位需要手动 置0, (strncpy 当目标缓冲区远远大于源字符串的长度时,剩下的空闲数据都需要置0,导致性能降低) 还要strnlen去计算实际长度 以上函数的滥用的太多 所以最好使用strlcpy(),由于是openBSD,gnulibc并没有,所以有可能要自己实现。(或者自己从bsd 中弄下来)
ftp://ftp.openbsd.org/pub/OpenBSD/5.7/src.tar.gz
http://www.opensource.apple.com/ 中可以找到任意OSX版本的代码 最新的OS X 是 10.10.2
这里多插一句,顺便看了下http://www.opensource.apple.com/source/tcp_wrappers/tcp_wrappers-20/tcp_wrappers/socket.c.diff
里面修改的也就是 同时兼容 IPV4/IPV6。
代码格式命名还是和UNP 这本书中一模一样,
我也不做评论了,大家自己看吧
strcpy
strcat
strncpy
strncat
就不一一列举了,都在目录 中
旧版本 http://www.opensource.apple.com/source/Libc/Libc-320/string/FreeBSD/
strlcpy.3
strlcpy.c
strlcpy
// man 手册中 A simple implementation of strncpy() might be: char *strncpy(char *dest, const char *src, size_t n) { size_t i; for (i = 0; i < n && src[i] != '\0'; i++) dest[i] = src[i]; for ( ; i < n; i++) dest[i] = '\0'; return dest; }
//=========== OpenBSD 5.7 版本的strlcpy OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp /* * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/types.h> #include <string.h> /* * Copy string src to buffer dst of size dsize. At most dsize-1 * chars will be copied. Always NUL terminates (unless dsize == 0). * Returns strlen(src); if retval >= dsize, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t dsize) { const char *osrc = src; size_t nleft = dsize; /* Copy as many bytes as will fit. */ if (nleft != 0) { while (--nleft != 0) { if ((*dst++ = *src++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src. */ if (nleft == 0) { if (dsize != 0) *dst = '\0'; /* NUL-terminate dst */ while (*src++) ; } return(src - osrc - 1); /* count does not include NUL */ } //===========MACOS Libc-1044.10.1版本的strlcpy #include <strings.h> size_t strlcpy(char * restrict dst, const char * restrict src, size_t maxlen) { const size_t srclen = strlen(src); if (srclen < maxlen) { memcpy(dst, src, srclen+1); } else if (maxlen != 0) { memcpy(dst, src, maxlen-1); dst[maxlen-1] = '\0'; } return srclen; }
strlcat
/* * Copyright (c) 2011 Apple, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include <strings.h> size_t strlcat(char * restrict dst, const char * restrict src, size_t maxlen) { const size_t srclen = strlen(src); const size_t dstlen = strnlen(dst, maxlen); if (dstlen == maxlen) return maxlen+srclen; if (srclen < maxlen-dstlen) { memcpy(dst+dstlen, src, srclen+1); } else { memcpy(dst+dstlen, src, maxlen-dstlen-1); dst[maxlen-1] = '\0'; } return dstlen + srclen; }
习题
netstat -ni -i显示网络接口信息,n 输出数值信息
netstat -nr -r显示路由表,-n输出数值地址
ifconfig eth0 可以看到设备MTU 1500(默认)
errno 可以在 include <errno.h> 中找到对因number的意义,man page也可以找到
getaddrinfo()可以取得IPv4/IPV6 地址,从而写出IPv4/IPV6通用的 代码。
MAC OS X inet_ntop 中还是用了static变量 ,多线程 还是会出现问题(http://www.opensource.apple.com/source/Libc/Libc-1044.1.2/net/inet_pton.c)
IP地址 字符串 与 网络字节序二进制 互相转换
n numberic 1100 0000 1010 1000 0000 0001 0000 0001
a ASC II "192.168.1.1"
inet_pton
inet_ntop
(p 代表 presentation n 代表numberic 支持IPV4IPv6,都是封装了inet_aton/inet_ntoa/ inet_addr 这些函数,加了些判断处理)
int inet_pton(int af, const char *src, void *dst);
inet_pton - convert IPv4 and IPv6 addresses from text to binary form string,转换 字符串地址 到 binary地址
struct sockaddr_in servaddr_IPV4; struct sockaddr_in6 servaddr_IPV6; inet_pton(AF_INET, "192.168.1.200", &servaddr_IPV4.sin_addr); inet_pton(AF_INET6, argv[1], &servaddr_IPV6.sin6_addr); //argv[1] 是ipv6 地址
推荐用新的inet_pton、inet_ntop 同时支持IPV4/IPV6
看到了sin_addr 结构之后可以用snprintf()自己实现(其实以前不知道这个函数,自己实现过很多遍)
/* Internet address. */ typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; };
既然知道是uint32_t 那么unsigned int 是 32bits, 0000 0000 0000 0000 每8bit代表一个段,0~255
要注意little-end, big-end 问题, 因为要转换到网络地址。
本地 x86/x86_x64 都是little-end, IBM POWER PC是big-end
网络上是big-end。
具体参见《深入理解计算机系统》最新是3rd,本书后面也有详细介绍。
On the i386 the host byte order is Least Significant Byte first,whereas the network byte order, as used on the Internet, is Most Significant Byte first.
htonl, htons, ntohl, ntohs - convert values between host and network byte order
htonl 主机字节序转换成网络字节序
#include <arpa/inet.h> uint32_t htonl(uint32_t hostlong); //host convert to network long uint16_t htons(uint16_t hostshort); //host convert to network short uint32_t ntohl(uint32_t netlong); // network convert to host long uint16_t ntohs(uint16_t netshort); // network convert to host short
16bit 用于 端口号
32bit 用于 IP地址(仅仅是IPV4)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)