概述

  要编写通过计算机网络通信的程序,首先要确定这些程序相互通信所用的协议。大多数网络是按照划分成客户和服务器来组织的。本章及后续章节的焦点是TCP/IP协议族,也可称为网际协议族。下图为客户与服务器使用TCP在同一个以太网中通信:

图1.1 客户与服务器使用TCP在同一个以太网进行通信

  同一网络中的客户机与服务器无需出于同局域网,上图1.1所示的是同一个局域网。下图1.2所示的是处于不同局域网的客户机与服务器,这两个局域网通过使用路由器连接到广域网。

图1.2 出于不同局域网的客户主机与服务器主机通过广域网进行连接

  如今讨论Unix是经常使用POSIC一词,它是一种被多数厂商采纳的标准。

一个简单的时间获取客户程序

  1. // 该头文件包含了大部分网络程序都需要的许多系统头文件
  2. #include "unp.h"
  3.  
  4. // main函数定义,其形式参数就是命令行参数
  5. int
  6. main(int argc, char **argv)
  7. {
  8. int sockfd, n;
  9. char recvline[MAXLINE + ];
  10. struct sockaddr_in servaddr;
  11.  
  12. if (argc != )
  13. err_quit("usage: a.out <IPaddress>");
  14.  
  15. // socket函数创建一个网际(AF_INET)字节流(SOCK_STREAM)套接字,该函数返回一个小整数描述符。如果socket函数调用失败,调用err_sys函数放弃程序运行
  16. if ( (sockfd = socket(AF_INET, SOCK_STREAM, )) < )
  17. err_sys("socket error");
  18.  
  19. // 把IP地址和端口号填入一个网际套接字地址结构(一个名为servadrr的sockdrr_in结构变量),使用bzero把整个结构清零
  20. bzero(&servaddr, sizeof(servaddr));
  21. // 置地址族为AF_INET,端口号为13,IP地址为第一个命令行参数的值(argv[1])
  22. // 网际套接字结构中IP地址和端口号必须使用特定格式,为此调用库函数htons去转换二进制端口号,又调用inet_pton去把ASCII命令行参数转换为合适的格式
  23. servaddr.sin_family = AF_INET;
  24. servaddr.sin_port = htons(); /* daytime server */
  25. if (inet_pton(AF_INET, argv[], &servaddr.sin_addr) <= )
  26. err_quit("inet_pton error for %s", argv[]);
  27.  
  28. // connect函数应用于TCP套接字时,将由它的第二个参数指向套接字地址结构指定的服务器建立一个TCP连接
  29. // 套接字地址结构的长度必须作为该函数的第三个参数指定
  30. if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < )
  31. err_sys("connect error");
  32.  
  33. // 使用read函数读取服务器的应答,并用标准I/O函数fputs输出结果
  34. // 把read放在循环以便读取完数据,当read返回0或者负数时终止循环
  35. while ( (n = read(sockfd, recvline, MAXLINE)) > ) {
  36. recvline[n] = ; /* null terminate */
  37. if (fputs(recvline, stdout) == EOF)
  38. err_sys("fputs error");
  39. }
  40. if (n < )
  41. err_sys("read error");
  42.  
  43. // 终止程序运行
  44. exit();
  45. }

  

  我们从官网www.unpcook.com下载源代码unpv13e.tar.gz。解压后进入文件夹。我的是Ubuntu系统。根据文件夹中Readme的提示输入相应的命令。

  1. redhat@redhat-virtual-machine:~/桌面/unpv13e$ ./configure
  2.  
  3. redhat@redhat-virtual-machine:~/桌面/unpv13e$ cd ./lib
  4. redhat@redhat-virtual-machine:~/桌面/unpv13e/lib$ make
  5.  
  6. redhat@redhat-virtual-machine:~/桌面/unpv13e$ cd ./libfree
  7. redhat@redhat-virtual-machine:~/桌面/unpv13e/libfree$ make
  8. // 如果报错如下,则需要在当前目录下打开inet_ntop.c文件
  9. // 将第60行的size_t size修改为socklen_t size 然后保存
  10. // 重新输入make后不报错即可
  11.  
  12. gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_ntop.o inet_ntop.c
  13. inet_ntop.c: In function inet_ntop’:
  14. inet_ntop.c::: error: argument size doesnt match prototype
  15. size_t size;
  16. ^
  17. In file included from inet_ntop.c:::
  18. /usr/include/arpa/inet.h::: error: prototype declaration
  19. extern const char *inet_ntop (int __af, const void *__restrict __cp,
  20. ^
  21. make: *** [inet_ntop.o] Error
  22.  
  23. redhat@redhat-virtual-machine:~/桌面/unpv13e/libfree$ cd ../libgai
  24. redhat@redhat-virtual-machine:~/桌面/unpv13e/libgai$ make
  25. // 以下的warning不用理会
  26. /usr/include/arpa/inet.h: In function inet_ntop’:
  27. inet_ntop.c::: warning: best.len may be used uninitialized in this function [-Wmaybe-uninitialized]
  28. if (best.base == - || cur.len > best.len)
  29. ^
  30. inet_ntop.c::: note: best.len was declared here
  31. struct { int base, len; } best, cur;
  32. ^
  33. gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_pton.o inet_pton.c
  34. ar rv ../libunp.a in_cksum.o inet_ntop.o inet_pton.o
  35. a - in_cksum.o
  36. a - inet_ntop.o
  37. a - inet_pton.o
  38. ranlib ../libunp.a
  39.  
  40. // 用root权限将以上编译生成的libunp.a 文件复制到/usr/lib目录中
  41.  
  42. redhat@redhat-virtual-machine:~/桌面/unpv13e/libgai$ cd ..
  43. redhat@redhat-virtual-machine:~/桌面/unpv13e$ sudo cp libunp.a /usr/lib
  44. [sudo] redhat 的密码:
  45.  
  46. // 打开unp.h文件将其中的#include "../config.h" 改成 #include "config.h"
  47. redhat@redhat-virtual-machine:~/桌面/unpv13e$ vim lib/unp.h
  48.  
  49. // 进入intro目录编译客户端文件并用root权限运行
  50. redhat@redhat-virtual-machine:~/桌面/unpv13e$ cd intro/
  51. redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ make daytimetcpcli
  52. redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ sudo ./daytimetcpcli 127.0.0.1
  53. // 错误提示无法连接
  54. connect error: Connection refused
  55.  
  56. // 我们先打开服务器
  57. redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ make daytimetcpsrv
  58. redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ sudo ./daytimetcpsrv
  59.  
  60. // 然后再打开另一个终端,在那里再运行客户端即可
  61. redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ sudo ./daytimetcpcli 127.0.0.1
  62. [sudo] redhat 的密码:
  63. Mon Dec ::

  

  上面提到了客户端获取时间的程序代码,下面为服务器端的程序。

  1. #include "unp.h"
  2. #include <time.h>
  3.  
  4. int
  5. main(int argc, char **argv)
  6. {
  7. int listenfd, connfd;
  8. struct sockaddr_in servaddr;
  9. char buff[MAXLINE];
  10. time_t ticks;
  11.  
  12. listenfd = Socket(AF_INET, SOCK_STREAM, );
  13.  
  14. // 填写一个网际套接字地址结构并调用bind函数,把服务器的端口捆绑到所创建的套接字中
  15.  
  16. bzero(&servaddr, sizeof(servaddr));
  17. servaddr.sin_family = AF_INET;
  18. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  19. servaddr.sin_port = htons(); /* daytime server */
  20.  
  21. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  22.  
  23. // 调用listen函数把该套接字转换成一个监听套接字,使来自客户端的连接可以在该套接字上由内核接受
  24. // socket、bind、listen这三个函数调用步骤是任何tcp服务器准备监听描述符的正常步骤
  25. // LISTENQ定义在头文件中,它指定系统内核允许在这个监听描述副符上排队的最大客户连接数
  26.  
  27. Listen(listenfd, LISTENQ);
  28.  
  29. // 服务器进程在accept调用中被投入睡眠,等待客户的连接
  30. // TCP连接的三次握手完毕时accept返回,其返回值是一个被称为已连接描述符的新描述符
  31. for ( ; ; ) {
  32. connfd = Accept(listenfd, (SA *) NULL, NULL);
  33.  
  34. // time函数获取当前时间,ctime函数把时间转换成直观可读的时间格式
  35. ticks = time(NULL);
  36.  
  37. // snprintf函数在这个字符串末尾添加一个回车符和一个换行符
  38. // write函数把结果字符串写给客户
  39.  
  40. snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
  41. Write(connfd, buff, strlen(buff));
  42. // 终止连接
  43. Close(connfd);
  44. }
  45. }

  

《UNIX网络编程 卷1:套接字联网API》读书笔记(一):网络编程简介的更多相关文章

  1. Unix网络编程--卷一:套接字联网API

    UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...

  2. [转载] 读《UNIX网络编程 卷1:套接字联网API》

    原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...

  3. 《Unix网络编程卷1:套接字联网API》读书笔记

    第一部分:简介和TCP/IP 第1章:简介 第2章:传输层:TCP.UDP和SCTP TCP:传输控制协议,复杂.可靠.面向连接协议 UDP:用户数据报协议,简单.不可靠.无连接协议 SCTP:流控制 ...

  4. VC++学习之网络编程中的套接字

    VC++学习之网络编程中的套接字 套接字,简单的说就是通信双方的一种约定,用套接字中的相关函数来完成通信过程.应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问 ...

  5. Linux网络编程:原始套接字简介

    Linux网络编程:原始套接字编程 一.原始套接字用途 通常情况下程序员接所接触到的套接字(Socket)为两类: 流式套接字(SOCK_STREAM):一种面向连接的Socket,针对于面向连接的T ...

  6. 网络编程与socket套接字

    网络编程与socket套接字 传输层 PORT协议 port是一种接口,数据通过它在计算机和其他设备(比如打印机,鼠标,键盘或监视器)之间,网络之间和其他直接连接的计算机之间传递 TCP协议 ​ 传输 ...

  7. Python黑帽编程2.8 套接字编程

    Python黑帽编程2.8 套接字编程 套接字编程在本系列教程中地位并不是很突出,但是我们观察网络应用,绝大多数都是基于Socket来做的,哪怕是绝大多数的木马程序也是如此.官方关于socket编程的 ...

  8. Python网络编程之TCP套接字简单用法示例

    Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...

  9. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

随机推荐

  1. mysql常用基础操作语法(四)--对数据的简单无条件查询及库和表查询【命令行模式】

    1.mysql简单的查询:select 字段1,字段2...  from tablename; 如果字段那里写一个*,代表查询所有的字段,等同于指定出所有的字段名,因此如果要查询所有字段的数据,一般都 ...

  2. PHP stream_context_create()作用和用法分析

    stream_content_create 创建并返回一个文本数据流并应用各种选项,可用于fopen(),filegetcontents()等过程的超时设置.代理服务器.请求方式.头信息设置的特殊过程 ...

  3. Maximum Entropy Model(最大熵模型)初理解

    0,熵的描述 熵(entropy)指的是体系的混沌的程度(可也理解为一个随机变量的不确定性),它在控制论.概率论.数论.天体物理.生命科学等领域都有重要应用,在不同的学科中也有引申出的更为具体的定义, ...

  4. zTree实现地市县三级级联数据库映射

    zTree实现地市县三级级联数据库映射 Province.hbm.xml: <?xml version="1.0" encoding="UTF-8"?&g ...

  5. java.sql.SQLException: Access denied for user 'sa'@'localhost' (using password: YES)

    1.错误描述 ERROR:2015-05-01 23:43:04[localhost-startStop-1] - HHH000319: Could not get database metadata ...

  6. JavaScript禁止浏览器默认行为

    JavaScript禁止浏览器默认行为 1.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...

  7. OpenStack_I版 1.准备过程

    openstack是一个开源云平台,python开发   此次部署为实验环境, 采用扁平化简单的网络架构部署                       优点:低耦合的,模块化            ...

  8. C#的动态链接库和XML配置

    今天对昨天的实例进行了改进和提高,将堆排序和冒泡排序封装在一个动态链接库中,提供函数调用和事件委托.此外加入XML进行配置,在XML中存入相关配置信息,提供一个单独的XmlClass对其进行操作,加深 ...

  9. CentOS 5.x 多个ISO文件 安装方法(VMware)

    CentOS下载地址:http://mirror.centos.org/centos/ CentOS版本:5.11 VMware版本:11.1.0 CentOS 5.11有两个ISO: CentOS- ...

  10. Java开发速度神器Lombok,Eclipse端安装使用教程

    一.Lombok简介 Lombok是一个代码生成器,可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法. 使用 ...