您如何编写网络代码?
1 编写网络代码的基本技能
1.1 了解网络协议
编写网络代码的基本要求是要熟练掌握相关的网络协议,了解通信协议的结构及含义,并能够实现将网络信息编码和解码的技能。现代网络技术是一种多层次的技术,并非只实现抽象的计算方法,它还需要理解基础层次上的网络协议,但这种理解是根据具体的网络协议而定。
1.2 了解网络编程技术
网络编程是网络信息处理的基础,它实现了网络数据的传输、控制、管理等功能,熟练掌握它是编写网络代码的重要基础。根据现阶段网络上应用不断增加而发展和改进,采用各种各样的编程技术实现统一的网络原理,其中包括服务器组件技术,如HTTP/TCP协议、VNC/RPC远程过程调用等;客户端编程技术,如HTML、XML、JavaScript等;网络安全技术,如SSL/TLS协议、IPSec等;网络管理技术,如SNMP、目录服务等;以及其它网络技术,如计算机网络、信息安全、多媒体等。
2 编写网络代码的要点
2.1 选择合适的网络通信协议
在编写网络代码之前必须选择合适的网络通信协议,否则将无法实现其网络功能。最常用的网络协议是TCP/IP协议,它已成为Internet上通用的网络标准;其它的网络协议也可以根据应用需求来选择,如HTTP协议、SMTP协议、FTP协议等。
2.2 熟悉和理解抽象层次的网络服务视图
不同的系统中有不同的抽象层次的网络服务视图,熟悉和理解这一视图是实现网络功能的基础,所以编写网络代码时要借助网络服务视图,如建立系统应用程序和传输层协议连接的会话层,用会话连接端口将网络上不同的主机逻辑连接起来,建立传输层网络连接,用于在网络上传输报文或数据,还要熟悉TCP/IP族协议、网络数据包拆分、封装、头部格式等。
2.3 探测网络状态
在实际的网络应用中,需要能够探测网络的状态,如tcp连接的状态,网络端口是否响应,主机的ip地址是否可达,数据传送过程中的数据丢失率,网络的延迟时间等,都需要具备探测网络状态的功能。
2.4 调用网络库函数
网络库提供了一些简单的API函数,用于写出优雅的网络代码。比如,WinSock库封装了Windows下常用的网络管理、系统调用、主机地址解析和文件传输功能;Linux系统中,一些常用的网络功能都有对应的C函数,如socket、bind、connect、listen、accept等。
3 编写网络代码的实例
3.1 实现TCP客户端程序
要实现TCP客户端程序,首先必须要先连接到一个TCP服务器,然后就可以定义需要发送到服务器和接收从服务器发来数据的缓冲区并建立连接,最后就可以根据应用需求实现读取和写入缓冲区数据的功能了。
服务端:
#include <stdio.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h>
int main() { int sockfd, newsockfd, port;
struct sockaddr_in serv_addr;
port = 8000;
/* 创建套接字 */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
/* 创建套接字失败 */
perror("ERROR creating socket");
return -1;
}
/* 设置通信地址 */
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
/* 绑定到套接字 */
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
/* 绑定失败 */
perror("ERROR on binding");
return -1;
}
/* 监听TCP套接字客户端请求 */
listen(sockfd, 5);
/* 接受客户端请求 */
newsockfd = accept(sockfd, NULL, NULL);
if (newsockfd < 0) {
/* 接受失败 */
perror("ERROR on accept");
return -1;
}
return 0;
}
客户端:
#include <stdio.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h>
int main() { int sockfd, port; struct sockaddr_in serv_addr; port = 8000;
/* 创建套接字 */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
/* 创建套接字失败 */
perror("ERROR creating socket");
return -1;
}
/* 设置服务端通信地址 */
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
/* 连接TCP服务器 */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
return -1;
}
return 0;
}
3.2 实现HTTP客户端程序
与TCP客户端程序类似,HTTP客户端程序也需要先连接到一个HTTP服务器,然后利用HTTP命令发送请求获取数据,最后将服务器的响应数据解析并保存到文件中。
#include <stdio.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h>
int main() { int sockfd, port, n; char *host = “www.example.com”; char request[1024], response[4096]; FILE *fp; struct hostent *server; struct sockaddr_in serv_addr; port = 80;
/* 创建套接字 */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
/* 创建套接字失败 */
perror("ERROR creating socket");
return -1;
}
/* 查找HTTP服务器地址 */
server = gethostbyname(host);
if (server == NULL) {
/* 查找失败 */
perror("ERROR, no such host");
return -1;
}
/* 设置服务器地址 */
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
/* 连接HTTP服务器 */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
return -1;
}
/* 生成HTTP请求 */
sprintf(request, "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host);
/* 发送HTTP请求 */
n = write(sockfd, request, strlen(request));
if (n < 0) {
/* 发送失败 */
perror("ERROR writing to socket");
return -1;
}
/* 读取HTTP响应 */
n = read(sockfd, response, sizeof(response) - 1);
if (n < 0) {