python编写操作系统实验报告_操作系统实验报告一

操作系统实验报告一

姓名:许恺

学号:2014011329

日期:9月29日

一.相关技术资料——》

Socket:

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。

绑定

函数原型:

int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);

参数说明:

socket:是一个套接字描述符。

address:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号。

address_len:确定address缓冲区的长度。

返回值:

如果函数执行成功,返回值为0,否则为SOCKET_ERROR。

接收

函数原型:

int recv(SOCKET socket, char FAR* buf, int len, int flags);

参数说明:

socket:一个标识已连接套接口的描述字。

buf:用于接收数据的缓冲区。

len:缓冲区长度。

flags:指定调用方式。取值:MSG_PEEK 查看当前数据,数据将被复制到缓冲区中,但并不从输入队列中删除;MSG_OOB处理带外数据。

返回值:

若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

创建进程,以及传递socket参数

bool bRet=::CreateProcess(

NULL,

szCommandLine,

NULL,

NULL,

FALSE,

CREATE_NEW_CONSOLE,

NULL,

NULL,

&si,

&pi);

if(bRet)

{

::CloseHandle(pi.hThread);

::CloseHandle(pi.hProcess);

1.函数说明:

WIN32API函数CreateProcess用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件。

2.函数原型:

BOOL CreateProcess

(

LPCTSTR lpApplicationName,

LPTSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes。

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCTSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation

);

3. 参数:

lpApplicationName:

指向一个NULL结尾的、用来指定可执行模块的字符串。

这个字符串可以使可执行模块的绝对路径,也可以是相对路径,在后一种情况下,函数使用当前驱动器和目录建立可执行模块的路径。

这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于lpCommandLine参数的最前面并由空格符与后面的字符分开。

这个被指定的模块可以是一个Win32应用程序。如果适当的子系统在当前计算机上可用的话,它也可以是其他类型的模块(如MS-DOS或OS/2)。

在Windows NT中,如果可执行模块是一个16位的应用程序,那么这个参数应该被设置为NULL,并且因该在lpCommandLine参数中指定可执行模块的名称。16位的应用程序是以DOS虚拟机或Win32上的Windows(WOW)为进程的方式运行。

lpCommandLine:

指向一个NULL结尾的、用来指定要运行的命令行。

这个参数可以为空,那么函数将使用参数指定的字符串当作要运行的程序的命令行。

如果lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数指定将被运行的模块的命令行。新运行的进程可以使用GetCommandLine函数获得整个命令行。C语言程序可以使用argc和argv参数。

如果lpApplicationName参数为空,那么这个字符串中的第一个被空格分隔的要素指定可执行模块名。如果文件名不包含扩展名,那么.exe将被假定为默认的扩展名。如果文件名以一个点(.)结尾且没有扩展名,或文件名中包含路径,.exe将不会被加到后面。如果文件名中不包含路径,Windows将按照如下顺序寻找这个可执行文件:

1.当前应用程序的目录。

2.父进程的目录。

Windows目录。可以使用GetWindowsDirectory函数获得这个目录。

4.列在PATH环境变量中的目录。

如果被创建的进程是一个以MS-DOS或16位Windows为基础的应用程序,lpCommandLine参数应该是一个以可执行文件的文件名作为第一个要素的绝对路径,因为这样做可以使32位Windows程序工作的很好,这样设置lpCommandLine参数是最强壮的。

传参

接收

二.报告内容

1. 阅读源代码,并调试,使得在自己本地机上能够显示出网页信息

//WebServer1.0.cpp : 定义控制台应用程序的入口点。//#include"stdafx.h"#include#include#include#include#include

#pragma comment(lib, "ws2_32.lib")

using namespacestd;//文件路径

static string dir = "D:\\xukai\\学习\\操作系统实验\\webServer1\\webServer\\Debug";void main(int argc, _TCHAR*argv[])

{//初始化WinSock库

WORD wVersionRequested;

WSADATA wsaData;

cout<< "初始化库成功" <

wVersionRequested= MAKEWORD(2, 2);int wsaret = WSAStartup(wVersionRequested, &wsaData);if(wsaret)return;

以上为网络编程框架//创建SOCKET

SOCKET socketSrv;

socketSrv= socket(AF_INET, SOCK_STREAM, 0);if (socketSrv ==INVALID_SOCKET)return;

cout<< "创建socket成功" <

SOCKADDR_IN addrSrv;

addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

addrSrv.sin_family=AF_INET;

addrSrv.sin_port= htons(80);

以上为创建socket包,定义参数//绑定套接字

if (bind(socketSrv, (struct sockaddr*)&addrSrv, sizeof(SOCKADDR)))

{//关闭连接

shutdown(socketSrv, 1);

closesocket(socketSrv);

WSACleanup();return;

}

cout<< "绑定套接字成功!" <

SOCKADDR_IN addrCli;int len = sizeof(SOCKADDR);//监听端口

if (listen(socketSrv, 5) ==SOCKET_ERROR)

{

printf("监听失败!\n");

}while (true)

{

SOCKET socketconn;

socketconn= accept(socketSrv, (SOCKADDR*)&addrCli, &len);//接受连接

客户端反应,服务端接收if (socketconn ==SOCKET_ERROR)

{

printf("接受连接失败!\n");return;

}

cout<< "连接成功" <

{*/

//连接成功后与客户端进行会话

char recvBuff[1024];stringsendBuff;stringlocDir;

ifstream fp;//接收请求

if (recv(socketconn, recvBuff, 1024, 0) ==SOCKET_ERROR)

{continue;

}

请求客户端发出的地址,放到recvBuff//读取http请求头

string recvBuffer =recvBuff;int posGet = recvBuffer.find("GET", 0);int posHttp = recvBuffer.find("HTTP", 0);//截取html文件路径

for (int pos = posGet + 4; pos

{if (recvBuffer[pos] == '/')

{

locDir.push_back('\\');continue;

}

locDir.push_back(recvBuffer[pos]);

}

翻译为文件地址路径

locDir= dir +locDir;//locDir.insert(0,1,'.');//打开http请求文件进行读取

fp.open(locDir.c_str(), std::ios::binary);//打开文件失败

if (!fp.is_open())

{

cout<< "请求文件" << locDir.c_str() << "不存在" <

}else//打开文件成功并读取

{char buffer[1024];while (fp.good() && !fp.eof())

{

fp.getline(buffer,1024);//将读取的内容追加入sendBuff中

sendBuff.append(buffer);

buffer[0] = '\0';

}

读文件,将文件写到sendBuff中

}

fp.close();//响应请求,将页面信息发送到客户端

if (send(socketconn, sendBuff.c_str(), sendBuff.length(), 0) ==SOCKET_ERROR)

{continue;

}

向客户端发送网页的内容

shutdown(socketconn,1);//}//关闭连接

closesocket(socketconn);

}//关闭连接

shutdown(socketSrv, 1);

closesocket(socketSrv);

WSACleanup();return;

}

2.每接收到客户端的链接请求,即创建一个进程,在此进程中完成与客户端的通讯。新创建的进程能够获得用户的请求的文件,在磁盘的指定位置将此文件读取出来,并经过socket将文件信息返回到申请客户端(浏览器),然后此进程执行结束。

Webserver.cpp//编写命令行参数

wchar_t pCmdLine[256];

wsprintf(pCmdLine, L"D:\\xukai\\学习\\操作系统实验\\webServer1\\Process\\Debug\\Process.exe %d", socketconn);//声明创建进程参数

LPPROCESS_INFORMATION pi=NULL;

STARTUPINFO si= { sizeof(si) };//创建进程并验证是否成功

BOOL ret = CreateProcess(LPCTSTR("Process.exe"),pCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, pi);if(ret) {//关闭子进程的主线程句柄

CloseHandle(pi->hThread);//关闭子进程句柄

CloseHandle(pi->hProcess);

}

Process.cpp//Process.cpp : 定义控制台应用程序的入口点。//#pragma once#include"stdafx.h"#include#include#include#include#include

#pragma comment(lib, "ws2_32.lib")

using namespacestd;//文件路径

static string dir = "D:\\xukai\\学习\\操作系统实验\\webServer1\\webServer\\Debug";void main(int argc, CHAR*argv[])

{

cout<< argc <

cout<< argv[0] <

cout<< argv[1] <

char recvBuff[1024];stringsendBuff;stringlocDir;

ifstream fp;

SOCKET socketconn= atoi(argv[1]);//接收请求

if (recv(socketconn, recvBuff, 1024, 0) ==SOCKET_ERROR)

{return;

}//读取http请求头

string recvBuffer =recvBuff;int posGet = recvBuffer.find("GET", 0);int posHttp = recvBuffer.find("HTTP", 0);//截取html文件路径

for (int pos = posGet + 4; pos

{if (recvBuffer[pos] == '/')

{

locDir.push_back('\\');continue;

}

locDir.push_back(recvBuffer[pos]);

}

locDir= dir +locDir;//locDir.insert(0,1,'.');//打开http请求文件进行读取

fp.open(locDir.c_str(), std::ios::binary);//打开文件失败

if (!fp.is_open())

{

cout<< "请求文件" << locDir.c_str() << "不存在" <

}else//打开文件成功并读取

{char buffer[1024];while (fp.good() && !fp.eof())

{

fp.getline(buffer,1024);//将读取的内容追加入sendBuff中

sendBuff.append(buffer);

buffer[0] = '\0';

}

}

fp.close();//响应请求,将页面信息发送到客户端

if (send(socketconn, sendBuff.c_str(), sendBuff.length(), 0) ==SOCKET_ERROR)

{return;

}

shutdown(socketconn,1);//}//关闭连接

closesocket(socketconn);return;

}

三.思考题

3.思考一下,为什么有时在IE浏览器中,请求网页在服务器中会收到多个请求?我们该怎样利用这种情况,来优化服务器?

答:因为一个网页分为文本和图片等,是不同的文件,所以需要分别请求,如果多线程并行传输就会快点。

4.能否解决网页名称为中文的问题

答:如果中文不能被识别的话可以通过两次编译码实现,转成字符串传输。

5.为什么在IE浏览器中显示的内容缺少了一些图片等信息?怎么来解决

答:个人认为是在客户发出申请,服务器返回socket包时有丢失,或者在阻塞的时候遗漏了信息包。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值