Java程序通过封装Windows API,提供给用户相关Socket类,实现一个简单的Web服务器较好理解。用c语言直接调用Windows API 中的winsocket相关函数实现简单的Web服务器,相对来说就复杂些了。通过了解这个实现过程,也能更好的理解Java封装后,实现开发的快捷和易于学习。
下面是这个小程序的C语言源代码:
#include//Winsock2.h头文件,里面有多种函数可以帮助使用Winsock. //Winsock是Windows下网络编程的规范,该规范是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口. #include //连接Ws2_32.lib这个库,ws2_32.lib是winsock2的库文件. #pragma comment(lib,"ws2_32.lib") main() { //typedef unsigned short WORD; WORD是无符号短整型的别名. WORD wVersionRequested; //WSA(Windows Sockets Asynchronous,Windows异步套接字),不少标识符用它做前缀. WSADATA wsaData; int err; //程序使用1.1版本的Socket,宏MAKEWORd( 1, 1 )的值是257的短整数,占两个字节,每个字节都是1. wVersionRequested = MAKEWORd( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); //返回值为0,WSAStartup()执行成功 if ( err != 0 ) { return; } //宏 LOBYTE和 HIBYTE分别检查 版本号的低8位和高8位是否是1. if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { //有一个不是1,注销 WSA的启动,并释放资源 WSACleanup(); return; } SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //设置socket 地址属性 SOCKADDR_IN addrSrv; //htonl()函数将一个32位数从主机字节顺序转换成无符号长整型的网络字节顺序(host to net long) . addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(9000); //bind(SOCKET s,const struct sockaddr *name,int namelen); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //listen(SOCKET s,int backlog);backlog指监听队列最大监听连接数 listen(sockSrv,5); //addrClient用于存放客户端socket 的地址属性 SOCKADDR_IN addrClient; //SOCKADDR结构体,用于存储参与(IP)Windows/linux套接字通信的计算机上的一个internet协议(IP)地址,长度是16字节 int len=sizeof(SOCKADDR); while(1) { //accept(SOCKET s,struct sockaddr *addr,int *addrlen)获取客户端的socket SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); char sendBuf[500]; //sprintf()函数把目标字符串装到 sendBuf数组中,第一个参数是指针类型。 sprintf(sendBuf,"HTTP/1.1 200 okrnContent-Type:text/htmlrnrnWelcome %s to here!",inet_ntoa(addrClient.sin_addr)); //strlen(sendBuf)+1,加1是让发送缓冲区大于要发送的字节数,第四个参数是传送方式(比如要传输带外数据),一般设置0即可。 send(sockConn,sendBuf,strlen(sendBuf)+1,0); char recvBuf[1500];//网络最大传输单元1500字节,在这两就设定这个大小就可以了 recv(sockConn,recvBuf,1500,0); printf("%sn",recvBuf); closesocket(sockConn); } }
代码使用 dev-C++5.11编辑和运行。在运行时注意添加一项编译配置, 在连接器命令行中添加“-lwsock32”命令。"工具"-"编译配置",如下图:
代码运行后,在浏览器中的访问如下图:
在服务器端看到浏览器的请求头如下图:



