Web服务器及客户端

实验  服务于多个请求的WEB服务器

【实验目的】

学习WEB服务器的编程,了解套接字监听、建立连接等机制。

【实验环境】

PC机(带有浏览器),寝室的局域网。

【实验重点及难点】

学习WEB的编程,学习套接字的编程。

实验内容

C++开发出一个能够并行服务于多个请求的多线程Web服务器。为每个请求响应对创建一个独立的TCP连接。每个连接由一个独立的线程来处理。还要有一个主线程,在主线程中,服务器监听要建立连接的客户端。

实验过程步骤

1、C++开发平台,编写服务器程序,通过修改,直到编译无错误,且运行成功为止。

2、C++开发平台,编写客户端程序,通过修改,直到编译无错误,且可以运行为止。

3、运行客户端程序,出现结果如下图:

 

Failed connect()。原因是服务器端还没打开(没有运行)。所以连接失败。

 

3、运行服务器端,出现结果如下图:

 

如图所示,主线程工作,监听要建立连接的客房端。

 

此时再运行客户端,则可以建立连接:且接收到从服务器端返回的消息:“这是服务器,这是服务器,收到请求,收到请求!”

建立连接,且收到回复消息!

 

4、Web浏览器测试此服务器

在傲游的地址栏里输入:http://192.168.1.6:6789/index.html,出现下图:

 

 

此时服务器端接收到请求:

 

 

再往傲游的地址栏里输入:http://192.168.1.6:6789,出现下图:

 

 

此时服务器端又接收到新的请求:

 

 

5、在寝室局域网内测试此服务器

 把客户端拿到寝室其他的机子上运行(为了测试,在所有验证的过程中,我把客户端程序中的服务器IP地址由127.0.0.1改为192.168.1.6

 

服务器端在我机子上运行,客户端分别拿到寝室其他电脑上运行,在客户端都接收到同样的回复

 

在服务器端,则出现如下图的结果:

前三个都是客户端在我机子上运行的结果,只是把IP改了而已

而后三个则是把客户端在其他的电脑上运行的结果。它们的IP分别是192.168.1.11192.168.1.7

 

6、在寝室局域网内用不同主机上的浏览器测试主机上的服务器

192.168.1.11的主机上分别输入http://192.168.1.6:6789,和http://192.168.1.6:6789/index.html,显示如下:

 

192.168.1.7的主机上分别输入http://192.168.1.6:6789/index.html,显示如下:

而在我这边的服务器上则收到了三个请求,如下所示:

 客户端程序代码

#include<winsock2.h>

#pragma comment(lib,"WS2_32")

class CInitSock

{

public:

       CInitSock(BYTE minorVer=2,BYTE majorVer=2)

       {//初始化WS2_32.dll

              WSADATA wsaData;

              WORD sockVersion=MAKEWORD(minorVer,majorVer);

              if(::WSAStartup (sockVersion,&wsaData)!=0)

              {

                     exit(0);

              }

       }

       ~CInitSock()

       {

              ::WSACleanup ();

       }

private:

       BYTE minorVer;

       BYTE majorVer;

};

#include<stdio.h>

CInitSock initSock;//初始化Winsock

int main()

{

       //创建套接字

       SOCKET s=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

       if(s==INVALID_SOCKET)

       {

              printf("Failed socket()/n");

              return 0;

       }

       //填写远程地址信息

       sockaddr_in servAddr;

       servAddr.sin_family=AF_INET;

       servAddr.sin_port=htons(6789);

       //下面要填写服务器程序所在机器的IP地址

       //防止程序运行在不同的主机上出错,在这用127.0.0.1

       servAddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.6");

       if(::connect(s,(sockaddr*)&servAddr,sizeof(servAddr))==-1)

       {

              printf("Failed connect()/n");

              return 0;

       }

       //接收数据

       char buff[256];

       int nRecv=::recv(s,buff,256,0);

       if(nRecv>0)

       {

              buff[nRecv]='/0';

              printf("服务器返回数据:%s",buff);

       }

       //关闭套接字

       ::closesocket(s);

       return 0;

}

 

 

 

 

客户端程序代码

#include<winsock2.h>

#pragma comment(lib,"WS2_32")

class CInitSock

{

public:

       CInitSock(BYTE minorVer=2,BYTE majorVer=2)

       {//初始化WS2_32.dll

              WSADATA wsaData;

              WORD sockVersion=MAKEWORD(minorVer,majorVer);

              if(::WSAStartup (sockVersion,&wsaData)!=0)

              {

                     exit(0);

              }

       }

       ~CInitSock()

       {

              ::WSACleanup ();

       }

private:

       BYTE minorVer;

       BYTE majorVer;

};

#include<stdio.h>

CInitSock initSock;

int main()

{

       SOCKET sListen=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

       if(sListen==INVALID_SOCKET)

       {

              printf("Failed socket()/n");

              return 0;

       }

       //填充sockaddr_in结构

       sockaddr_in sinAddr;

       sinAddr.sin_family=AF_INET;

       sinAddr.sin_port=htons(6789);

       sinAddr.sin_addr.S_un.S_addr=INADDR_ANY;

       //绑定这个套接字到一个本地地址

       if(::bind(sListen,(LPSOCKADDR)&sinAddr,sizeof(sinAddr))==SOCKET_ERROR)

       {

              printf("Failed bind()/n");

              return 0;

       }

       //进入监听模式

       if(::listen(sListen,2)==SOCKET_ERROR)

       {

              printf("Failed listen()/n");

              return 0;

       }

       else printf("监听当中……/n");

       //循环接受客户的连接请求

       sockaddr_in remoteAddr;

       int nAddrLen=sizeof(remoteAddr);

       SOCKET sClient;

       char szText[]="这是服务器,这是服务器,收到请求,收到请求!/r/n";

//     if(!(::closesocket(sClient)))

//     printf("继续监听……/n");

       while(TRUE)

       {//接受新连接

              sClient=::accept(sListen,(SOCKADDR*)&remoteAddr,&nAddrLen);

              if(sClient==INVALID_SOCKET)

              {

                     printf("Failed accept()");

                     continue;

              }

              printf("接受到一个连接:%s/r/n",inet_ntoa(remoteAddr.sin_addr));

              //向客户端发送数据

              ::send(sClient,szText,strlen(szText),0);

              //关闭同客户端的连接

              ::closesocket(sClient);

       }

       //关闭监听套接字

//     printf("关闭套接字");

       ::closesocket(sListen);

       return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值