13.TCP/IP和网络编程
TCP/IP协议
TCP/IP 是互联网的基础。TCP代表传输控制协议。IP代表互联网协议。目前有两个版本的IP,即IPv4和IPv6。IPv4使用32位地址,IPv6则使用128位地址。本节围绕IPv4进行讨论,它仍然是目前使用最多的IP版本。TCP/IP的组织结构分为几个层级,通常称为TCP/IP堆栈。
顶层是使用TCP/IP的应用程序。用于登录到远程主机的ssh、用于交换电子邮件的邮件、用于Web页面的http等应用程序需要可靠的数据传输。通常,这类应用程序在传输层使用TCP。另一方面有些应用程序,例如用于查询其他主机的ping命令,则不需要可靠性。这类应用程序可以在传输层使用UDP来提高效率。
顶层是使用TCP/IP的应用程序。用于登录到远程主机的ssh、用于交换电子邮件的邮件、用于Web页面的http等应用程序需要可靠的数据传输。通常,这类应用程序在传输层使用TCP。另一方面有些应用程序,例如用于查询其他主机的ping命令,则不需要可靠性。这类应用程序可以在传输层使用UDP来提高效率。
网络编程
-
网络编程平台
用户可选择使用服务器上的用户账号进行编程或者直接使用PC设备 -
服务器-客户机计算模型
大多数网络编程任务都基于服务器-客户机计算模型。在服务器-客户机计算模型中,我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机。在 UDP 中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在TCP 中、服务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电路。建立连接后,服务器和客户机可以交换连续的数据流。
- 套接字编程
在网络编程中,TCP/IP 的用户界面是通过一系列C语言库函数和系统调用来实现的,这些函数和系统调用统称为套接字 API。为了使用套接字API,我们需要套接字地址结构,它用于标识服务器和客户机。netdb.h和 sys/socketh中有套接字地址结构的定义。
套接字地址
struct sockaddr_in{
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
struct in_addr{
uint32_t s_addr;
};
send()/read()以及recv/write()
建立连接后,两个TCP主机都可以使用send()/write()发送数据,并使用recv()/read()接收数据。它们唯一的区别是send()和recv()中的flag参数不同,通常情况下可以将其设置为0。
asize_t send(int sockfd, const void *buf, size_t len, int flags), asize_t write(sockfd, void *buf, size_t, len)
ssize_t recv(int sockfd, void *buf, bize_t len, int flags); asize_t read(sockfd, void *buf, size_t len);
通用套接字地址结构
sockaddr
struct sockaddr
{
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};
●TCP/IP 网络的 sin_family 始终设置为AF_INET。
● sin_port 包含按网络字节顺序排列的端口号。
● sin addr是按网络字节顺序排列的主机 IP地址。
-
UDP
UDP是用户数据报协议。
UDP在IP上运行,用于发送/接收数据报。与IP类似,UDP不能保证可靠性,但是快速高效。它可用于可靠性不重要的情况。
ping使用的是UDP协议。 -
TCP
TCP(传输控制协议)是一种面向连接的协议,用于发送/接收数据流。TCP也可在IP上运行,但它保证了可靠的数据传输。通常,UDP类似于发送邮件的USPS,而TCP类似于电话连接。
WEB和CGI编程
万维网(WWW)或Web是互联网上的资源和用户组合,它使用超文本传输协议(HTTP)(RFC 26161999)进行信息交换。自 20世纪 90年代初问世以来,随着互联网能力的不断扩展,Web已经成为世界各地人们日常生活中不可或缺的一部分。因此,对于计算机科学的学生来说.了解这项技术非常重要。
实践
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#define MAXLINE 256
#define PORT 6552
void sys_err(char *msg){
perror(msg);
exit(-1);
}
int main(int argc , char **argv){
int sockFd,n;
char recvLine[MAXLINE];
struct sockaddr_in servAddr;
if (argc != 2) {
sys_err("usage: a.out <IPaddress>");
}
sockFd=socket(AF_INET,SOCK_STREAM,0);
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(PORT);
if (inet_pton(AF_INET,argv[1],&servAddr.sin_addr) <= 0) {
sys_err("inet_pton error");
}
connect(sockFd,(struct sockaddr *)&servAddr,sizeof(servAddr));
while((n=read(sockFd,recvLine,MAXLINE)) >0 ){
recvLine[n] = '\0';
if(fputs(recvLine,stdout) == EOF){
sys_err("fputs error");
}
}
if(n <0){
sys_err("read error");
}
return 0;
}
运行结果为: