zoukankan      html  css  js  c++  java
  • 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 这本书中一模一样,
    我也不做评论了,大家自己看吧

    最新版本代码
    strlcpy.c
    strlcat

    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] != ''; i++)
                       dest[i] = src[i];
                   for ( ; i < n; i++)
                       dest[i] = '';
    
                   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++) == '')
    				break;
    		}
    	}
    
    	/* Not enough room in dst, add NUL and traverse rest of src. */
    	if (nleft == 0) {
    		if (dsize != 0)
    			*dst = '';		/* 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] = '';
            }
            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] = '';
        }
        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)


  • 相关阅读:
    【笔记】程序员编程艺术 字符串转换成整数
    解决Eclipse 项目报错:Unbound classpath container: ‘JRE System Library [JavaSE-1.7]
    python_day1(初始Python)
    ActiveMQ 复杂类型的发布与订阅
    win8.1 Framework3.5安装不上的问题
    JVM探秘:内存溢出
    JVM探秘:Java对象
    JVM探秘:Java内存区域
    Vmware安装的linux系统开机黑屏,点关闭就显示虚拟机忙怎么怎么解决?
    Java基础--面向对象(上)
  • 原文地址:https://www.cnblogs.com/scotth/p/4618333.html
Copyright © 2011-2022 走看看