web服务为一个长时间运行的程序(守护程序 daemon),一般是由客户端发送请求,服务端响应来自网络的请求发送网络消息
有些较为复杂的网络应用还需要异步回调通信:服务端向客户端发送请求
客户与服务器之间的信息流在其中一端是向下通过协议栈,跨网络后,在另一端是向上通过协议栈
上图是在同一个局域网之中通信,下面展示的是不同局域网中的客户与服务器
本文地址:http://wuyudong.com/2016/08/09/2425.html,转载请注明源地址。
下面是一个简单的时间获取客户程序例子:
#include "unp.h" int main(int argc, char **argv) { int sockfd, n; 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; 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) { recvline[n] = 0; /* null terminate */ if (fputs(recvline, stdout) == EOF) err_sys("fputs error"); } if (n < 0) err_sys("read error"); exit(0); }
下面分析一下代码:
unp.h 头文件是书的作者对某些系统头文件、常量等进行封装
创建TCP套接字
socket函数创建一个网际(AF_INET)字节流(SOCK_STREAM)套接字,它是TCP套接字的花哨名字。该函数返回一个小整数的描述符
指定服务器的IP地址和端口
把服务器的IP地址和端口号填入一个网际套接字地址结构(一个名为servaddr的sockaddr_in结构变量)。
使用bzero把整个结构清零,设置地址族为AF_INET,端口号为13,IP地址的为第一个命令行参数的值,网际套接字地址结构中IP地址和端口号这两个成员必须使用特定格式,可以调用库函数htons去转换二进制端口号,又调用库函数inet_pton去把ASCII命令行参数转换成合适的格式
connect函数应用于一个TCP套接字时,将与由它的第二个参数指向的套接字地址结构指定的服务器建立一个TCP连接
使用read函数读取服务器的应答,并用标准的I/O函数fputs输出结果
exit终止程序的执行
为了让上面的程序能够在IPv6上运行,进行一些简单的修改:
#include "unp.h" int main(int argc, char **argv) { int sockfd, n; struct sockaddr_in6 servaddr; char recvline[MAXLINE + 1]; if (argc != 2) err_quit("usage: a.out <IPaddress>"); if ( (sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) err_sys("socket error"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin6_family = AF_INET6; servaddr.sin6_port = htons(13); /* daytime server */ if (inet_pton(AF_INET6, argv[1], &servaddr.sin6_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) { recvline[n] = 0; /* null terminate */ if (fputs(recvline, stdout) == EOF) err_sys("fputs error"); } if (n < 0) err_sys("read error"); exit(0); }
Comments