服务器回射程序设计.docx
- 文档编号:4006814
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:17
- 大小:39.82KB
服务器回射程序设计.docx
《服务器回射程序设计.docx》由会员分享,可在线阅读,更多相关《服务器回射程序设计.docx(17页珍藏版)》请在冰点文库上搜索。
服务器回射程序设计
网络编程技术实验报告
实验名称
实验四基于数据报套接字的回射程序设计与实验
队别
姓名
学号
实验日期
2015.12.9
实验报告要求:
1.实验目的2.实验要求3.实验环境4.实验作业5.问题及解决
6.思考问题7.实验体会
【实验目的】
1.巩固套接字编程
2.熟悉流式套接字编程
【实验要求】
使用流式套接字编程实现回射程序,具体包括:
1.客户端:
主动请求建立连接,接收界面输入字符串,发送数据给服务器,接收服务器返回的应答,输出显示。
2.服务器:
在指定端口上提供服务,接收客户端的发送的回射请求字符串,将接收到的内容回射给客户端,输出显示。
3.提炼出网络操作的基本功能,构造网络操作类,修改原有程序
【实验环境】
DEVC++
【实验作业】
网络操作类设计:
classCSocketFrame
{
public:
intstart_up();
intclean_up();
intset_address(char*hname,char*sname,structsockaddr_in*sap,char*protocol);
intquit(SOCKETs);
SOCKETtcp_server(ULONGuIP,USHORTuPort);
SOCKETtcp_server(char*hname,char*sname);
SOCKETtcp_client(char*hname,char*sname);
SOCKETtcp_client(ULONGuIP,USHORTuPort);
};
intCSocketFrame:
:
start_up(void)
{
WORDwVersionRequested;
WSADATAwsaData;
intiResult;
wVersionRequested=MAKEWORD(2,2);
iResult=WSAStartup(wVersionRequested,&wsaData);
if(iResult!
=0)
{
printf("WSAStartup调用错误,错误号:
%d\n",WSAGetLastError());
return-1;
}
/*
if(LOBYTE(wsaData.wVersion!
=2||HIBYTE(wsaData.wVersion)!
=2))
{
printf("无法找到可用的WSD版本\n");
WSACleanup();
return-1;
//告诉用户无法找到可用的WSD
}
else
{
printf("WS2.2初始化成功!
\n");
}*/
return0;
}
intCSocketFrame:
:
clean_up(void)
{
intiResult;
iResult=WSACleanup();
if(iResult==SOCKET_ERROR)
{
//WSACleanup()调用失败
printf("WSACleanup调用错误,错误号:
%d\n",WSAGetLastError());
return-1;
}
else
printf("Winsocketdll释放成功!
\n");
return0;
}
intCSocketFrame:
:
set_address(char*hname,char*sname,structsockaddr_in*sap,char*protocol)
{
structservent*sp;
structhostent*hp;
char*endptr;
unsignedshortport;
unsignedlongulAddr=INADDR_NONE;
//将地址结构socketsddr_in初始化为0,并将地址族设为AF_INET
memset(sap,0,sizeof(*sap));
sap->sin_family=AF_INET;
if(hname!
=NULL)
{
//如果hname不为空,转化地址格式
ulAddr=inet_addr(hname);
if(ulAddr==INADDR_NONE||ulAddr==INADDR_ANY)
{
//调用错误,调用gethostbyname获得主机地址
hp=gethostbyname(hname);
if(hp==NULL)
{
printf("未知的主机名,错误号:
%d\n",WSAGetLastError());
return-1;
}
sap->sin_addr=*(structin_addr*)hp->h_addr;
}
else
sap->sin_addr.S_un.S_addr=ulAddr;
}
else
//如果调用者没有指明一个主机名或地址,则设为通配地址
sap->sin_addr.s_addr=htonl(INADDR_ANY);
//尝试转换sname为一个整数
port=(unsignedshort)strtol(sname,&endptr,0);
if(*endptr=='\0')
{
//如果成功转化为网络字节序
sap->sin_port=htons(port);
}
else
{
//如果失败,则假定是一个服务名称,通过getservbyname()函数获得端口号
sp=getservbyname(sname,protocol);
if(sp==NULL)
{
printf("未知服务,错误号:
%d\n",WSAGetLastError());
return-1;
}
sap->sin_port=sp->s_port;
}
return0;
}
intCSocketFrame:
:
quit(SOCKETs)
{
intiResult=0;
iResult=closesocket(s);
if(iResult==SOCKET_ERROR)
{
printf("closesocket调用错误,错误号:
%d\n",WSAGetLastError());
return-1;
}
iResult=clean_up();
returniResult;
}
SOCKETCSocketFrame:
:
tcp_server(char*hname,char*sname)
{
SOCKETListenSocket;
intiResult=0;
sockaddr_inlocal;
constinton=1;
//为服务器的本机地址设置用户输入的地址以及端口号
if(set_address(hname,sname,&local,(char*)"tcp")!
=0)
return-1;
//创建套接字
ListenSocket=socket(AF_INET,SOCK_STREAM,0);
if(ListenSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
WSACleanup();
return-1;
}
//绑定服务器地址
iResult=bind(ListenSocket,(structsockaddr*)&local,sizeof(local));
if(iResult==-1)
{
printf("bind函数调用错误!
错误号:
%d\n",WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return-1;
}
//设置函数为监听状态,监听队列长度为NLISTEN
iResult=listen(ListenSocket,SOMAXCONN);
if(iResult==SOCKET_ERROR)
{
printf("Listen函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ListenSocket);
return-1;
}
returnListenSocket;
}
SOCKETCSocketFrame:
:
tcp_server(ULONGuIP,USHORTuPort)
{
SOCKETListenSocket=INVALID_SOCKET;
intiResult=0;
sockaddr_inlocal;
constinton=1;
//为服务器的本机地址设置用户输入的地址以及端口号
memset(&local,0,sizeof(local));
local.sin_family=AF_INET;
local.sin_addr.S_un.S_addr=htonl(uIP);
local.sin_port=htons(uPort);
ListenSocket=socket(AF_INET,SOCK_STREAM,0);
if(ListenSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
clean_up();
return-1;
}
//绑定服务器地址
iResult=bind(ListenSocket,(structsockaddr*)&local,sizeof(local));
if(iResult==SOCKET_ERROR)
{
printf("bind函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ListenSocket);
return-1;
}
//设置函数为监听状态,监听队列长度为NLISTEN
iResult=listen(ListenSocket,SOMAXCONN);
if(iResult==SOCKET_ERROR)
{
printf("Listen函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ListenSocket);
return-1;
}
returnListenSocket;
}
SOCKETCSocketFrame:
:
tcp_client(char*hname,char*sname)
{
intiResult=0;
structsockaddr_inpeer;
SOCKETClientSocket;
//为服务器的地址peer设置用户输入的地址以及端口号
if(set_address(hname,sname,&peer,(char*)"tcp")!
=0)
return-1;
//创建套接字
ClientSocket=socket(AF_INET,SOCK_STREAM,0);
if(ClientSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
clean_up();
return-1;
}
//请求建立连接
iResult=connect(ClientSocket,(structsockaddr*)&peer,sizeof(peer));
if(iResult==SOCKET_ERROR)
{
printf("connect函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ClientSocket);
return-1;
}
returnClientSocket;
}
SOCKETCSocketFrame:
:
tcp_client(ULONGuIP,USHORTuPort)
{
intiResult=0;
structsockaddr_inpeer;
SOCKETClientSocket;
//为服务器的地址peer设置用户输入的地址以及端口号
memset(&peer,0,sizeof(peer));
peer.sin_family=AF_INET;
peer.sin_addr.S_un.S_addr=htonl(uIP);
peer.sin_port=htons(uPort);
//创建套接字
ClientSocket=socket(AF_INET,SOCK_STREAM,0);
if(ClientSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
clean_up();
return-1;
}
//请求建立连接
iResult=connect(ClientSocket,(structsockaddr*)&peer,sizeof(peer));
if(iResult==SOCKET_ERROR)
{
printf("connect函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ClientSocket);
return-1;
}
returnClientSocket;
}
服务器代码设计:
#defineMAXLINE10000
#defineECHOPORT"7210"
inttcp_server_fun_echo(SOCKETs)
{
intiResult=0;
charrecvline[MAXLINE];
do
{
memset(recvline,0,MAXLINE);
//接收数据
iResult=recv(s,recvline,MAXLINE,0);
if(iResult>0)
{
printf("服务器接收到数据:
%s\n",recvline);
//回射程序已经收到的数据
iResult=send(s,recvline,iResult,0);
if(iResult==SOCKET_ERROR)
{
printf("send函数调用错误,错误号:
%ld\n",WSAGetLastError());
iResult=-1;
}
else
printf("服务器发送数据%s\n",recvline);
}
else
{
if(iResult==0)
printf("对方连接关闭,退出\n");
else
{
printf("recv函数调用错误,错误号:
%d\n",WSAGetLastError());
iResult=-1;
}
break;
}
}while(iResult>0);
returniResult;
}
intmain(intargc,char*argv[])
{
CSocketFrameframe;
intiResult=0;
SOCKETListenSocket,ConnectSocket;
//输入参数合法性检查
if(argc!
=1)
{
printf("usage:
EchoTCPServer");
return-1;
}
//初始化
frame.start_up();
//创建服务器的流式套接字并在指定端口号上监听
ListenSocket=frame.tcp_server((char*)NULL,(char*)ECHOPORT);//改成全部任意
if(ListenSocket==-1)
return-1;
printf("服务器准备好回射服务。
。
。
\n");
for(;;)
{
ConnectSocket=accept(ListenSocket,NULL,NULL);
if(ConnectSocket!
=INVALID_SOCKET)
{
//建立连接成功
printf("\r\n建立连接成功\n\n");
//回射
iResult=tcp_server_fun_echo(ConnectSocket);
//如果出错,关闭当前连接的套接字,继续接受其他客户端的请求
if(iResult==-1)
printf("当前连接已关闭或出错!
\n");
}
else
{
printf("accept函数调用错误,错误号:
%d\n",WSAGetLastError());
frame.quit(ListenSocket);
return-1;
}
//关闭套接字
if(closesocket(ConnectSocket)==SOCKET_ERROR)
printf("closesocket函数调用错误,错误号:
%d\n",WSAGetLastError());
}
frame.quit(ListenSocket);
return0;
}
客户端代码设计:
#defineECHOPORT"7210"
#defineMAXLINE10000
inttcp_client_fun_echo(FILE*fp,SOCKETs)
{
intiResult;
charsendline[MAXLINE],recvline[MAXLINE];
//初始化缓冲区
memset(sendline,0,MAXLINE);
memset(recvline,0,MAXLINE);
//循环发送用户输入的数据,并接受服务器返回的应答,直到用户输入Q结束
while(fgets(sendline,MAXLINE,fp)!
=NULL)
{
if(*sendline=='Q')
{
printf("inputend!
\n");
//用户发送数据结束
iResult=shutdown(s,SD_SEND);
if(iResult==SOCKET_ERROR)
{
printf("shutdown函数调用错误,错误号:
%d",WSAGetLastError());
}
return0;
}
iResult=send(s,sendline,strlen(sendline),0);
if(iResult==SOCKET_ERROR)
{
printf("send函数调用错误,错误号:
%d",WSAGetLastError());
return-1;
}
printf("\r\n客户端发送数据:
%s\r\n",sendline);
memset(recvline,0,MAXLINE);
iResult=recv(s,recvline,MAXLINE,0);
if(iResult>0)
printf("客户端收到数据:
%s\r\n",recvline);
else
{
if(iResult==0)
printf("服务器终止!
\n");
else
printf("recv函数调用错误,错误号:
%d",WSAGetLastError());
break;
}
memset(sendline,0,MAXLINE);
}
returniResult;
}
intmain(intargc,char*argv[])
{
CSocketFrameframe;
intiResult;
SOCKETClientSocket;
//输入参数合法性检查
/*
if(argc!
=2)
{
printf("usage:
EchoTCPServer");
return-1;
}*/
//WSD初始化
frame.start_up();
//创建客户端的流式套接字
printf("连接成功,请输入回射字符串。
。
。
\n");
ClientSocket=frame.tcp_client((char*)argv[1],(char*)ECHOPORT);
if(ClientSocket==-1)
return-1;
//开始回射请求的发送与接收
iResult=tcp_client_fun_echo(stdin,ClientSocket);
frame.quit(ClientSocket);
}
实验结果:
我是在两台不同的电脑上做的实验,实验结果如下:
服务器:
客户端:
【实验中出现问题及解决方法】
1.平台的问题
因为自己是使用win10的,开始装上VisualStudio2015出现了很多问题,比如库文件缺失,相关项目类型没有装的问题。
解决方法:
暂时使用DEVC++,然后自己对VS进行相关配置,已经差不多了,后续会尝试转移到VS平台。
【思考问题】
(自己在试验过程中想到的问题)
1.如果服务器端口号设定为任意可不可以?
不可以,因为客户端会不知道服务器的端口。
2.上述设计的服务器有没有考虑多个客户端的问题?
可以多个客户端同时连接成功,但是只有首先连入的那个可以与服务器进行通信!
【实验体会】
因为涉及到网络操作结构类的构造,代码量比较大,当然很多在本节中并没有使用,但考虑到日后要进行使用,减少后续编程的工作量,在本次结构体设计中,对可能用到的基本操作进行了一次性的设计。
但是后续的工作就进行的比较顺利。
还是比较有自豪感的!
因为参考了试验课本,以后仍需勤加练习,才能够更好地掌握流式套接字编程。
成绩
优
良
中
及格
不及格
教师签名:
日期:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 服务器 射程 设计