网络程序设计(socketAPI)

Similar documents
引言 ftp 工作原理 FTP 客户端思考练习 要点回顾 1 ip 地址结构 2 字节顺序转换函数 3 IP 格式转换函数 2 / 29

Slide 1

Chapter #

VoIP Make a Rtp Call VoIP Abstract... 2 VoIP RTP...3 Socket IP...9 Config Two Voice-hub

Chapter 5- 运输层 (5)-2017


华清远见就业优势倍增项目手册

《信息通信网》实验指导书

Slide 1

<4D F736F F F696E74202D20A1B6CFEEC4BFD2BB20B3F5CAB6BCC6CBE3BBFACDF8C2E7A1B7C8CECEF1C8FD20CAECCFA A1A24950D0ADD2E9BACD4950B5D8D6B72E707074>

Chap04

它是使用标准 Unix 文件描述符 (file descriptor) 和其它程序通讯的方式 什么? 你也许听到一些 Unix 高手 (hacker) 这样说过 : 呀,Unix 中的一切就是文件!. 那个家伙也许正在说到一个事实 :Unix 程序在执行任何形式的 I/O 的时候, 程序是在读或者写

(Methods) Client Server Microsoft Winsock Control VB 1 VB Microsoft Winsock Control 6.0 Microsoft Winsock Control 6.0 1(a). 2

Linux網路傳輸設定

Microsoft PowerPoint - Socket programming.ppt [相容模式]

第 1 章 概 述 1.1 计 算 机 网 络 在 信 息 时 代 中 的 作 用 1.2 计 算 机 网 络 的 发 展 过 程 *1.2.1 分 组 交 换 的 产 生 *1.2.2 因 特 网 时 代 *1.2.3 关 于 因 特 网 的 标 准 化 工 作 计 算 机 网 络 在

C6_ppt.PDF

ebook

24 数据包 Sockets 阻塞 select()-- 多路同步 I/O 重新回顾 TCP,UDP 47 4 什么是 socket 你经常听到人们谈论着 socket, 或许你还不知道它的确切含义 现在让我告诉你 : 它是使用标准 Unix 文件描述符 (fi

/3/15 1, linux. linux,,. : 1.NAT ; 2. (load balance, virtual server);; 3. ; 4. ; 5. 6.VPN; 7. ; 8. ; 9.. (,

untitled

epub 33-8

新・明解C言語入門編『索引』

UDP 8.2 TCP/IP OSI OSI 3 OSI TCP/IP IP TCP/IP TCP/IP Transport Control Protocol TCP User Datagram Protocol UDP TCP TCP/IP IP TCP TCP/IP TC

C 1

static struct file_operations gpio_ctl_fops={ ioctl: gpio_ctl_ioctl, open : gpio_open, release: gpio_release, ; #defineled1_on() (GPBDAT &= ~0x1) #def

MASQUERADE # iptables -t nat -A POSTROUTING -s / o eth0 -j # sysctl net.ipv4.ip_forward=1 # iptables -P FORWARD DROP #

untitled

TCP/IP TCP/IP OSI IP TCP IP IP TCP/IP TCP/IP

untitled

Iinux中select函数的使用

ebook140-8

IP505SM_manual_cn.doc

Microsoft Word - 第5章.doc

/ / (FC 3)...

ebook

目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas

嵌入式Linux块设备驱动开发解析

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf ("%d", & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9

(Guangzhou) AIT Co, Ltd V 110V [ ]! 2

C/C++语言 - C/C++数据

CC213

財金資訊-80期.indd

epub 61-2


2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

untitled

Ps22Pdf

ebook140-9

Simulator By SunLingxi 2003

untitled

AL-M200 Series

Data Server_new_.doc

ACE

Istoric. Concepte si notiuni de baza.

Socket Programming in the Banking Collection Service Counter System


_汪_文前新ok[3.1].doc

目 录(目录名)

Microsoft PowerPoint - 数据通信-ch1.ppt

第3章.doc

C++ 程式設計

C/C++ 语言 - 循环

穨IC-1000

公務員懲戒法實務及新制

大小通吃-糖尿病


(Microsoft Word - outline for Genesis 9\243\2721\243\25529.doc)

穨Shuk-final.PDF

招行2002年半年度报告全文.PDF

Microsoft Word _4

郑州大学(下).doc

厨房小知识(六)


Transcription:

前言通信模型重要函数 网络程序设计 (socketapi) 孙永科 西南林业大学 2010 年 9 月 6 日 1 / 40

上节回顾 前言通信模型重要函数上节回顾本章重点 阻塞和非阻塞 socket 通信模型大字节顺序小字节顺序网络字节顺序 2 / 40

本章重点 前言通信模型重要函数上节回顾本章重点 1 通信模型基本概念 Socket 通信 Socket 地址 Socket 函数 2 重要函数获取主机信息 Name Services 插口状态测试 3 / 40

基本概念 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 应用程序能够访问 TCP/IP 协议所提供的服务, 都是通过调用接口与 TCP/IP 协议进行交互 套接字的特点 1 套接字提供了许多综合的功能, 这些功能支持使用众多可能的协议进行网络通信 ; 2 套接字调用把所有的 TCP/IP 协议看做一个单一的协议 族 4 / 40

基本概念 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 套接字 1 套接字是一个指向传输提供者的句柄 ; 2 套接字可以通过函数 socket() 来创建 ; 当系统调用 socket 函数来初始化一个套接字时, 操作系统就分配一个新的数据结构来保存通信所需的信息, 并在文件描述符中填入新的条目 5 / 40

套接字类型 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 1 流式套接字 : 这时最长用的套接字,TCP/IP 协议簇中的 TCP(Transport Control Protocol) 协议使用此类接口, 它提供面向连接的 无差错的 发送先后顺序一致的 包长度不限和非重复的网络信息包的传输 2 数据包套接字 :TCP/IP 协议簇中的 UDP(User Datagram Protocol) 协议使用此类接口, 它是无连接的服务, 义独立的数据报进行网络传输, 数据报的最大长度为 32KB, 传输不保证顺序性 可靠性和无重复性, 它通常用于单个报文传输或可靠性不重要的场合 3 原始报套接字 : 提供对网络下层通信协议 ( 如 IP 协议 ) 的直接访问, 他一般不是提供给普通用户的, 只有超级用户才能创建原始套接字, 主要用于开发新的协议或用于提取协议较隐蔽的功能 6 / 40

前言 通信模型 重要函数 基本概念 Socket 通信 Socket 地址 Socket 函数 套接字编程原理 Server Socket() bind() listen() accept() block,wait for client connection request read() deal with data response write() Client socket() connect() write() read() 套接字编程均采用客户机 / 服务器的协作模式, 即由客户进程向服务器进程发出请求, 服务器进程执行被请求的任务并将结果返回给客户进程 左图讨论的是 TCP 协议使用面向连接的流式套接字 close() close() 7 / 40

Address of Sockets 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 端口 (port) : 是一个 16bits 的地址 端口的分类及特点 1 熟知端口 (Well-Known port): 数值为 1 1023, 有 Internet 分配数值权威机构分配给一些最常用的应用程序使用 2 一般端口 : 数值为 1024 65535, 只要不发生冲突, 任何应用程序均可分配使用 3 通常, 服务器需要用户指定自己的端口, 而客户进程的端口是由操作系统自动分配, 系统能够保证不分配正在使用的端口给客户进程 8 / 40

Address 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 套接字中定义了地址族和协议族, 一个协议族可以使用一个或多个地址族来定义地址的表示方式 AF and PF 1 地址族符号常量 AF_INET 2 协议族符号常量 PF_INET 9 / 40

前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 IPv4 插口地址结构 IPv4 插口地址结构在头文件 <netinet/inh> 中定义, 结构名称为 sockaddr_in IPv4 struct sockaddr_in{ uint8_t sin_len;/*length of structure*/ sa_family_t sin_family;/*af_inet*/ in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; } 10 / 40

前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 套接字编程中用到的函数 Server Socket() bind() listen() accept() block,wait for client connection request read() deal with data response write() Client socket() connect() write() read() 编程中的几个重要函数 1 socket() 2 bind() 3 listen() 4 accept() 5 connect() 6 read() 7 write() 8 close() close() close() 11 / 40

Socket() 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 原型 #include <sys/socketh> int socket(int family,int type,int protocol); - family: 协议族 - type: 插口类型 - protocol: 协议 功能及说明 : 1 创建一个用于网络通信的套接字 ; 2 参数中需要指明使用的协议族和服务类型 ; 3 该调用返回新创建的套接字的描述符 ( 句柄 ) 12 / 40

前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 Parameters of socket family family AF_INET AF_INET6 type type SOCK_STREAM SOCK_DGRAM SOCK_RAW protocol 含义 IPv4 IPv6 含义字节流 (TCP) 数据报 (UDP) 原始插口 (RAW) 协议, 一般置为 0, 除非在原始 (RAW) 插口上 13 / 40

bind() 原型 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 #include <sys/socketh> int bind(int sockfd, const sockaddr *myaddr, socklen_t addrlen); - sockfd: 插口描述符 - *myaddr: 地址结构指针 - addrlen: 地址的长度 功能及特点 1 为一个套接字指明本地端点地址, 包括协议地址和端口号 ; 2 一般情况下, 客户进程没有必要调用该函数, 系统会自动为其选择一个本地地址 ; 3 对于服务器需要帮定到一个已知的端口上, 并在此端口上等 待连接 14 / 40

sockaddr 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 struct sockaddr { /* Common data: address family and length */ SOCKADDR_COMMON (sa_); }; /* Address data */ char sa_data[14]; 15 / 40

connect() 原型 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 #include <sys/socketh> int connect (int sockfd, const sockaddr *servaddr, socklen addrlen); - sockfd: 插口描述符 - *servaddr: 地址结构指针 - addrlen: 地址的长度 功能及特点 1 客户进程同远程服务器进行连接 ; 2 若调用失败, 则插口必须关闭 ; 重新调用 socket() 函数创建新的插口, 并重新进行连接 16 / 40

端口测试 I 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 1 #include <stdioh> 2 #include <stdlibh> 3 #include <sys/socketh> 4 #include <netinet/inh> 5 #include <netdbh> 6 #include <errnoh> 7 #include <stringsh> 8 #include <sys/timeh> 10 #define MAXBUFSIZE 1024 /* 发送和接收缓存的最大长度 */ 12 int main(int argc, char *argv[]) 13 { 14 int sockfd=0; /* 插口描述符 */ 15 char des_addr[]= 202203132241 ; 16 in_port_t SERVER_PORT=21; 17 struct sockaddr_in serveraddr; /* 服务器地址 */ 18 /* 产生 TCP 插口 */ 19 if ((sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0) 20 { 21 printf( 产生插口失败, 退出 \n ); 17 / 40

前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 端口测试 II 22 exit(1); 23 } 24 /* 填写服务器地址结构 */ 25 bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); 26 serveraddrsin_family = AF_INET; 27 serveraddrsin_port = htons(server_port); 28 inet_aton(des_addr, &serveraddrsin_addr); 30 /* 发起连接请求 */ 31 if (connect(sockfd, (struct sockaddr *)&serveraddr, sizeof( serveraddr)) < 0){ 33 printf( 连接请求失败 : errno=%d\n,errno); 34 close(sockfd); /* 重新建连, 必须重新产生新插口, 关闭原插口 */ 35 }else{ 36 printf( 连接成功 \n ); 37 } 38 return 1; 39 } 18 / 40

listen() 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 原型 #include <sys/socketh> int listen(int sockfd,int backlog); - sockfd: 插口描述符 - backlog: 插口排队的最大连接数 功能 面向连接的服务器将接口准备接收来自客户进程的连接 19 / 40

accept() 原型 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 #include <sys/socketh> int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); - sockfd: 插口描述符 - *cliaddr: 连接对方的地址指针 - *addrlen: 连接对方的地址长度 功能及特点 1 接收下一个传入的连接 ; 2 为每个新的连接请求创建一个新的套接字, 并将新套接字的描述符返回个调用者, 而原来的套接字继续监听 ; 3 服务器可在新的套接字上传送数据, 在使用完后服务器将关闭该套接字 20 / 40

close() 前言通信模型重要函数基本概念 Socket 通信 Socket 地址 Socket 函数 原型 #include <unistdh> int close (int sockfd); 功能及特点 终止通信并释放描述符 ; 21 / 40

前言 通信模型 重要函数 基本概念 Socket 通信 Socket 地址 Socket 函数 shutdown() 原型 #include <sys/socketh> int shutdown (int sockfd, int howto); 关闭方式 SHUT_RD SHUT_WR SHUT_RDWR 说明关闭读通道 接收缓存被清空, 但可以继续发送 关闭写通道 不再发送, 但可以继续接收数据 关闭读写通道 功能及特点 1 按指定方式关闭套接字的读, 写, 读写通道 ; 2 该函数并没有关闭套接字和释放描述符 22 / 40

Other functions 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 getsockname() #include <sys/socketh> int getsockname (int sockfd, struct sockadd *peeraddr, socklen_t *addrlen); 功能 : 得到分配给套接字的本地地址 ; getpeername() #include <sys/socketh> int getpeername (int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen); 功能 : 当连接到达后, 从套接字中获得远端机器的地址 23 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 gethostbyname 原型 #include <netdbh> struct hostent *gethostbyname(const char *hostname); 1 struct hostent{ 2 char *h_name; //host name 3 char **h_aliases; //host list 4 int h_addrtype; //type 5 int h_length; //IP numbers count 6 char **h_addr_list; //IP list 7 #define h_addr h_addr_list[0] 8 } 24 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 获取主机信息 I 1 #include <stdioh> 2 #include <netdbh> 3 #include <arpa/ineth> 4 #include <netinet/inh> 5 struct hostent *p1; 6 struct in_addr *sin_addr; 7 char name[]= localhost ; 8 char **p3; 10 void main(){ 12 p1=gethostbyname(name); 14 if (p1==null){ 15 printf( Error occured!\n ); 16 } 17 else{ 18 printf( 主机正式名称为 :%s\n,p1 >h_name); 20 for(p3=p1 >h_aliases;*p3!=null;p3++) 21 printf( 别名 :%s\n,*p3); 25 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 获取主机信息 II 23 if(p1 >h_addrtype==af_inet){ 25 for(p3=p1 >h_addr_list;*p3!=null;p3++){ 26 sin_addr=(struct in_addr *)*p3; 27 printf( 主机的地址为 IP:%s\n,inet_ntoa(*sin_addr)); 28 } 29 } 30 } 31 } 26 / 40

程序说明 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 #include <stdioh> // 标准的输入输出 #include <netdbh> // 包含 gethostbyname 定义 #include <arpa/ineth> // 包含 inet_ntoa 定义 #include <netinet/inh> // 包含 in_addr 结构体定义 编译 : gcc -g -o gethostbyname gethostbynamec 运行 : /gethostbyname 运行结果 syk@syk-laptop:example$ /gethostbyname 主机正式名称为 :localhost 别名 :localhostlocaldomain 别名 :localhost 别名 :syk-laptop 别名 :ip6-localhost 别名 :ip6-loopback 主机的 IP 地址为 :127001 27 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 Names and Address Families 1 域名和 IP 的映射 访问某个网站, 即使它更改的 ISP 2 访问函数 :getaddrinfo int getaddrinfo (const char *hoststr, const char *servicestr, const struct addrinfo *hints, struct addrinfo **results) 参数说明 : 1- 指向主机字符串或 IP 地址的指针 2- 指向端口或者服务名称的指针 3- 描述返回信息的类型 4- 返回结果的列表指针 函数的返回值 0: 成功 ; 非 0: 失败 28 / 40

addrinfo 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 1 struct addrinfo { 2 int ai_flags; //Flags to control info resolution 3 int ai_family; //Family: AF_INET,AF_INET6,AF_UNSPEC 4 int ai_socktype; //Socket type: SOCK_STREAM,SOCK_DGRAM 5 int ai_protocol; //Protocol: 6 socklen_t ai_addrlen; //Length of socket address ai_addr 7 struct sockaddr *ai_addr; //Socket address for socket 8 char *ai_canonname; //Canonical name 9 struct addrinfo *ai_next; //Next addrinfo in linked list 10 }; 注包含此结构的程序, 在使用 gcc 编译时应使用参数 :--std=c89; 或者使用 g++ 编译 推荐使用 g++ 29 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 访问名称服务 I 1 #include <stdioh> 2 #include <stdlibh> 3 #include <stringh> 4 #include <netdbh> 5 #include <arpa/ineth> 6 int main() { 8 char *addrstring = wwwgooglecom ; 9 char *portstring = www ; 11 //Tell the sstem what kind(s) of address info we want 12 struct addrinfo addrcriteria; 13 memset(&addrcriteria,0,sizeof(addrcriteria)); 14 //Any address family 15 addrcriteriaai_family = AF_UNSPEC; 16 addrcriteriaai_socktype = SOCK_STREAM; 30 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 访问名称服务 II 17 addrcriteriaai_protocol = IPPROTO_TCP; 19 //Get address(es) associated with the specified name/service 20 struct addrinfo *addrlist; 21 int rtnval = getaddrinfo(addrstring,portstring,& addrcriteria,&addrlist); 22 if(rtnval!= 0){ 23 printf( find error!\n ); 24 exit(2); 25 } 27 //Display returned address 28 struct addrinfo *addr; 29 for (addr=addrlist; addr!=null; addr=addr > ai_next) 30 { 31 //print out the IP address 31 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 访问名称服务 III 32 printf( IP:%s,inet_ntoa(((struct sockaddr_in *)addr >ai_addr) >sin_addr)); 33 printf( %u,ntohs(((struct sockaddr_in *)addr >ai_addr) >sin_port)); 34 fputc( \n, stdout); 36 } 38 //Free addrinfo allocated in getaddrinfo() 39 freeaddrinfo(addrlist); 40 exit(0); 41 } 32 / 40

程序测试 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 - 查找 wwwgooglecom 上的 www 服务 /getaddrinfo-1 IP:6624989104 80 - 查找 wwwgooglecn 上的 80 端口服务 /getaddrinfo-1 IP:20320839104 80 IP:2032083999 80 - 查找 wwwgooglecom 上的 git 服务 /getaddrinfo-1 IP:6624989104 9418 33 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 One name -> Multi-address 1 Rubustness If any single host fails, the service continues 2 Load balancing we can spread the load over multiple servers 34 / 40

select() 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 原型 #include <sys/timeh> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) 功能及特点 阻塞监视一组插口的状态 ( 可读 可写或出现带外数据 ), 直到指定的插口状态发生变化或阻塞时间到 判断套接字上是否存在数据, 或能否向一个套接字写入数据 35 / 40

select() 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 select() 可用同时监视三个互不相关的描述符集内的状态变化, 可用如下宏来设置描述符集 void FD_CLR(int fd,fd_set fdset); int FD_ISSET(int fd,fd_set *fdset); void FD_SET(int fd,fd_set *fdset); void FD_ZERO(fd_set *fdset); 36 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 select 写测试步骤 1 将套接字添加到 writefds 集合中 ; 2 调用 select() 函数 ; 3 判断该套接字是否仍在 writefds 集合中 ; 4 若是, 则证明该接口可写 37 / 40

测试插口 I 前言通信模型重要函数获取主机信息 Name Services 插口状态测试 1 #include <stdioh> 2 #include <sys/socketh> 3 #include <sys/timeh> 4 #include <sys/typesh> 5 #include <unistdh> 6 fd_set ufds;// 插口描述符集 7 struct timeval tv;// 超时间隔 8 int fd1,fd2,maxfd,status; 9 void main(){ 10 fd1=socket(af_inet,sock_stream,0); 11 fd2=socket(af_inet,sock_stream,0); 12 for(;;){ 13 /* 每次调用前都必须重新设置描述符集 */ 14 FD_ZERO(&ufds); 15 FD_SET(fd1,&ufds); 38 / 40

前言通信模型重要函数获取主机信息 Name Services 插口状态测试 测试插口 II 16 FD_SET(fd2,&ufds); 17 printf( fd1=%d\n,fd1); 18 printf( fd2=%d\n,fd2); 19 maxfd=((fd1>fd2)?(fd1):(fd2))+1; 21 /* 每次调用前都必须重新设置超时时间 */ 22 tvtv_sec=0; 23 tvtv_usec=4000; 24 /* 超时时间为 4 秒 */ 25 status=select (maxfd,null,&ufds,null,&tv); 27 if(status==0){ 28 /* 超时处理 */ 29 printf( a\n ); 30 } else if(status== 1){ 31 /* 出错处理 */ 39 / 40

前言 通信模型 重要函数 获取主机信息 Name Services 插口状态测试 测试插口 III 32 printf( b\n ); 33 }else{ 35 if (FD_ISSET(fd1,&ufds)){ 36 /* 可以往发 fd1 上发送数据 */ 37 printf( fd1 is writeable\n ); 38 } 39 if(fd_isset(fd2,&ufds)){ 40 /* 可以往 fd2 上发送数据 */ 41 printf( fd2 is writeable\n ); 42 } 43 } 44 } 45 } 40 / 40