1、TCP/IP协议层次,各层协议?
答:应用层、传输层、网络层、链路层;
1)应用层:FTP、Telnet、SMTP、HTTP、RIP、NFS、DNS
(2)传输层:传输控制协议TCP与用户数据报协议UDP
(3)网际层协议:网际协议IP、网际控制报文协议ICMP、网际主机组管理协议IGMP、
(4)网络接口层:地址解析协议ARP和RARP
2、在Internet中定位一个应用进程标识?(网间进程标识=传输协议+主机IP地址+端口号)
3、什么是TCP,什么是UDP,有什么不同?
答:TCP:传输控制协议;是一种面向连接的、可靠的、基于字节流的运输层通信协议。
UDP:用户数据报协议;是一个简单的面向数据报的传输层(transport layer)协议。
区别:UDP传输可靠性低,传输速度快,面向非连接,.;TCP传输可靠性高,传输速度慢,面向连接;
4、什么是c/s模型?工作过程?
答:客户-服务器模式;
工作过程:
首先服务器方要先启动,并根据请示提供相应服务,过程如下:
(1)打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求;
(2) 等待客户请求到达该端口;
(3)服务器接收到服务请求,处理该请求并发送应答信号。为了能并发地接收多个客户的服务请求,要激活一个新进程或新线程来处理这个客户请求,服务完成后,关闭此新进程与客户的通信链路,并终止 ;
(4) 返回第二步,等待另一客户请求;
(5) 关闭服务器。
客户端:
1. 打开一通信通道,并连接到服务器所在主机的特定端口;
2. 向服务器发送服务请求报文,等待并接收应答;继续提出请求……;
3. 请求结束后关闭通信通道并终止。
5、什么是套接字?分类?什么是数据报套接字,流试套接字?
答:通信的基础,是支持网络协议数据通信的基本接口;
分类: 流式套接字(SOCK_STREAM)是面向连接、可靠的、无差错的传输服务,基于TCP;数据报套接字(SOCK_DGRAM)是面向无连接、不可靠、与数据包形式发送的传输服务,基于UDP;原始套接字是允许直接访问较低层的 协议,基于ip,icmp。
6、基于TCP(流式套接字),UDP(数据包套接字)编程模式?
答:TCP模式:
服务器端程序:
1、创建套接字(socket)。
2、将套接字绑定到一个本地地址和端口上(bind)。
3、将套接字设为监听模式,准备接收客户请求(listen)。
4、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
5、用返回的套接字和客户端进行通信(send/recv)。
6、返回,等待另一客户请求。
7、关闭套接字。
客户端程序:
1、创建套接字(socket)。
2、向服务器发出连接请求(connect)。
3、和服务器端进行通信(send/recv)。
4、关闭套接字。
UDP模式:
服务器端(接收端)程序:
1、创建套接字(socket)。
2、将套接字绑定到一个本地地址和端口上(bind)。
3、等待接收数据(recvfrom)。
4、关闭套接字。
客户端(发送端)程序:
1、创建套接字(socket)。
2、向服务器发送数据(sendto)。
3、关闭套接字。
7、本机字节顺序,网络字节顺序.
答:本机字节顺序:不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序。
网络字节顺序:网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式
8、基本操作函数.
答:启动函数WSAStartup()和终止函数 WSACleanup()。
启动函数WSAStartup():
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData );
wVersionRequested指Winsock的版本号(高字节指定副版本,低字节指定主版本)。Winsock 2.2表示为0x0202;也可使用宏MAKEWORD(X,Y),X为高位字节,Y为低位字节,该宏创建一个被指定变量连接而成的WORD变量。例如:
WSAStartup(0x0202,&wsaData);
WSAStartup(MAKEWORD(2,2),&wsaData);
lpWSAData是一个指向WSADATA结构的指针。当该函数被调用时,返回关于Windows Sockets实现的详细信息。
启动函数WSAStartup():
终止:对于每一个WSAStartup函数的成功调用(即成功加载WinSock动态库后),在最后都对应一个WSAC1eanLlp调用,以便释放为该应用程序分配的资源,终止对WinSock动态库的使用。
WSAClean()函数。
9、编程.(客户机与服务器)
答:/*----------------------------------------------------
* 程序: 服务器程序,TalkS_TCP.cpp
* 目的: 创建一个套接字,接收来自客户的连接请求;
* 输出来自客户的信息;
* 通过键盘输入信息,把信息发送给客户。
*----------------------------------------------------
*/
#include
#include
main() {
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1);
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) { return; }
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return; }
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv; //定义一个地址结构体的变量
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
//htons把一个u_short类型从主机字节序转换为网络字节顺序
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
listen(sockSrv,5); //侦听,一次可有5个在等待。
char sendBuf[100];
char recvBuf[100];
char temp[200];
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
int n;
SOCKET sockConn;
sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
while(1) { n=recv(sockConn,recvBuf,100,0);
if ( n>0 )
printf("%d chars from server: %s\n",n,recvBuf);
if('q'==recvBuf[0]) //对方想退出 {
send(sockSrv,"q",strlen("q")+1,0);
printf("chat end!\n");
break; }
printf("please input data:\n");
gets(sendBuf);//从标准输入流中得到一行数据
send(sockConn,sendBuf,strlen(sendBuf)+1,0); //使用连接套接字,而不要监听套接字;flags设置为0即可}
closesocket(sockConn);
WSACleanup();//最后需要WSACleanUp()清除套接字。
}
客户端程序代码
/*----------------------------------------------------
* 程序: 客户方程序,TalkC_TCP.cpp
* 目的: 创建一个套接字,通过网络连接一个服务器
* 通过键盘输入信息,把信息发送给服务器;
* 输出来自服务器的信息。
*----------------------------------------------------
*/
#include
#include
main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err,n;
wVersionRequested = MAKEWORD( 1, 1);
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) { return; }
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return; }
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
if(connect(sockClient,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR))<0)
printf("Connect failed! \n"); //传送数据所需要的变量定义
char sendBuf[100];
char recvBuf[100];
char temp[200];
int len=sizeof(SOCKADDR);
while(1) {
printf("please input data:\n");
gets(sendBuf);
send(sockClient,sendBuf,strlen(sendBuf)+1,0);
n=recv(sockClient,recvBuf,100,0);
if ( n>0 )
printf("%d chars from server: %s\n",n,recvBuf);
if ('q'==recvBuf[0])
{ send(sockClient,"q",strlen("q")+1,0);
printf("chat end!\n");
break; } sprintf(temp,"%s:%s",inet_ntoa(addrSrv.sin_addr),recvBuf);
printf("%s\n",temp); }
closesocket(sockClient);
WSACleanup();
}
10、MFC与套接功能有关的类(CAsyncSocket CSocket)
答:CAsyncSocket类;CScket类;
11、两个类之间的区别联系?
答:CASyncSocket:异步方式。发送就返回结果无阻塞现象
CSocket:同步方式。只有发送完成后才返回结果有阻塞现象;
总的来说,CAsyncSocket是异步非阻塞类. CSocket是CAsyncSocket的派生类.是同步塞类.
12、两个类基于流式套接字编程步骤?
答:CAyncSocket类:
服务器(server) 客户机(client)
1、//构造一个套接字 //构造一个套接字
CAyncSocket sockSrvr; CAyncSocket sockClient;
2、//创建Socket句柄,绑定到 //创建Socket句柄,使用默认参数
指定的端口 sockClient.Create();
sockSrvr.Create(nPort);
3、//启动监听,时刻准备接受
连接请求
sockSrvr.Listen();
4、 //请求连接到服务器
sockClient.connet(strAddr.nport);
5、//构造一个新的空的套接字来接受连接
CAyncSocket sockRecv;
sockSrvr.Accept(sockRecv);
6、//接受数据 //发送数据
sockRecv.Receive(pBuf , nLen); sockClient.Send(pBuf , nLen));
7、//发送数据 //接收数据
sockRecv.Send(pBuf , nLen); sockClient.Receive(pBuf , nLen);
8、//关闭套接字对象 //关闭套接字对象
sockRecv.Close(); sockClient.Close();
CSocket类
1、 服务器端
(1)CSocket sockServ; // 创建空的服务器端监听套接字对象。
(2)sockServ.Create( nPort ); // 用众所周知的端口,创建监听套接字对象的底层套接字句柄。
(3)sockServ.Listen(); // 启动对于客户端连接请求的监听。
(4)CSocket sockRecv; // 创建空的服务器端连接套接字对象。
sockServ.Accept( sockRecv); // 接收客户端的连接请求,并将其他的任务转交给连接套接字对象。
(5)CSockFile* file ;
file = new CSockFile( &sockRecv); //创建文件对象并关联到连接套接字对象。
6)CArchive* arIn, arOut;// 归档对象必须关联到文件对象。
arIn = CArchive(&file, CArchive::load); //创建用于输入的归档对象,
arOut = CArchive( &file, CArchive::store); // 创建用于输出的归档对象。
(7)arIn >> dwValue; // 进行数据输入。
adOut << dwValue; // 进行数据输出。输入或输出可以反复进行。
(8)sockRecv.Close();
sockServ.Close(); // 传输完毕,关闭套接字对象。
2.客户端
(1)CSocket sockClient; // 创建空的客户机端套接字对象。
(2)sockClient.Create( ); // 创建套接字对象的底层套接字。
(3)sockClient.Connect( strAddr, nPort ); // 请求连接到服务器。
(4)CSockFile* file ;
file = new CSockFile( &sockClent); //创建文件对象,并关联到套接字对象。
(5)CArchive* arIn, arOut; // 归档对象必须关联到文件对象。
arIn = CArchive(&file, CArchive::load); // 创建用于输入的归档对象,
arOut = CArchive( &file, CArchive::store); // 创建用于输出的归档对象。
(6)arIn >> dwValue; // 进行数据输入。
adOut << dwValue; // 进行数据输出。输入或输出可以反复进行。
(7)sockClient.Close(); // 传输完毕,关闭套接字对象。
13、类能接受那些网络事件?(6种)
答:FD_READ事件:通知有数据可读。
FD_WRITE事件:通知可以写数据。
FD_ACCEPT事件:通知监听套接字有连接请求可以接受。
FD_CONNECT事件:通知请求连接的套接字,连接的要求已被处理。
FD_CLOSE事件:通知套接字已关闭。
FD_OOB事件:通知将有带外数据到达。
13、什么是WinInet,其作用?((编写客户机支持协议)
答:Windows Internet 扩展应用程序高级编程接口,是专为开发具有Internet功能的客户机应用程序而提供的。支持HTTP、FTP、Gopher协议;作用:借助 WinInet 接口,可不必去了解 Winsock、TCP/IP 和特定 Internet 协议的细节就可以编写出高水平的 Internet 客户端程序。
14、MFC WinInet有哪些类?(5种)
答:会话类CInternetSession、连接类、网络文件类、文件查询类、异常类
15、FTP客户机(利用WinInet 函数,编程步骤?)
答:(1).调用InternetAttemptConnection()函数测试主机与Internet的连接状态
(2)调用InternetOpen()函数,创建HINTERNET会话根句柄
(3)调用InternetConnect()函数创建FTP连接句柄
(4)实现各种常见的FTP操作,依赖于FTP连接句柄,将它作为函数的第一个参数
16、WinSocket I/O的两种工作模式?什么是阻塞,非阻塞.
答:阻塞模式、非阻塞模式;阻塞:称同步模式,阻塞套接字的I/O操作工作情况比较确定,即调用、等待、返回。大部分情况下,I/O操作都能成功地完成,只是花费了等待的时间,容易编程;非阻塞模式:称异步模式,使用非阻塞套接字,需要编写更多的代码,因为必须恰当地把握调用I/O函数的时机,尽量减少无功而返的调用,还必须详加分析每个Winsock调用中收到的错误,采取相应的对策,这种I/O操作的随机性使得非阻塞套接字显得难于操作。
17、阻塞解决方法,多线程机制,非阻塞解决方法?(五种套接字输入模式)
答:阻塞的解决方法:多线程机制
非阻塞的解决方法:选择(Select)、异步选择(WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I/O(Overlapped I/O)和完成端口(Completion Port)五种I/O模型
创建MFC下的工作线程步骤?
答:1.编辑实现控制函数
2.创建并启动工作线程
18、Select模型?
答:select模型的操作步骤
使用 FD_ZERO宏初始化感兴趣的每一个 fd_set集合。
使用 FD_SET宏将要检查的套接字句柄添加到感兴趣的每个 fd_set集合中,相当在指定的fd_set集合中,设置好要检查的I/O活动。
调用 select函数,然后等待。select完成并返回后,会修改每个 fd_set结构,删除那些不存在待决I/O操作的套接字句柄,在各个fd_set集合中返回符合条件的套接字。
根据select的返回值,使用 FD_ISSET宏,对每个fd_set集合进行检查 ,判断一个特定的套接字是否仍在集合中 ,便可判断出哪些套接字存在着尚未完成(待决)的I/O操作。
知道了每个集合中“待决”的I/O操作之后,对相应的套接字的I/O进行处理 ,然后返回步骤1,继续进行select处理。
SOCKET s; //定义一个套接字
fd_set fdread; //定义一个套接字集合变量
int ret; //返回值
//创建一个套接字,并接受连接
.......
// 管理该套接字上的输入/输出
while(TRUE)
{
FD_ZERO(&fdread); //调用select()之前要清除套接字集合
FD_SET(s, &fdread); //将套接字 s 添加到fdread集合中
//调用select()函数,并等待它的完成,
//这里只是想检查s是否有数据可读
if ((ret = select(0, &fdread, NULL, NULL, NULL)) == SOCKET_ERROR)
{
…… //处理错误的代码
}
//返回值大于零,说明有符合条件的套接字
//对于本例这个简单的情况,select()的返回值应是1。
//如果程序处理更多的套接字,返回值可能大于1,
//应用程序应检查特定的套接字是否在返回的集合中
if ( ret > 0)
{
if (FD_ISSET(s, &fdread))
{
…… // 对该套接字进行读操作
}
}
}
19、HTTP会话周期?(4部分)
答:连接、请求、响应、断开;
具体:
建立TCP/IP连接
Web客户机向服务器发送HTTP请求
服务器向客户机回送HTTP响应
断开TCP/IP连接
20、CHtml View类 建一个web浏览器
21、STMP协议 POP3协议
答:简单邮件传送协议SMTP(Simple Mail Transfer Protocol),SMTP协议采用C/S模式,专用于电子邮件的发送,规定了发信人把邮件发送到收信人的电子邮箱的全过程中,SMTP客户与SMTP服务器这两个相互通信的进程之间应如何交换信息。
用来接收电子邮件的POP邮局协议最初是在1984年发表的RFC918中定义的,1985年的RFC937发表了它的第二个版本。随着POP协议的广泛使用,1988年的RFC1081又发表了它的第三版本,简称POP3
22、邮件格式(邮件头 邮件体)
答:所有的信头字段包括四部分,字段名(field name),紧跟冒号":" (colon),后跟字段体(field body),最后以回车换行符(CRLF)终止。即
信头字段 = 字段名:字段体
23、用WinSocket实现电子邮件中发送会话的步骤?
(1)启动SMTP服务器,在指定的传输层端口监听客户端的连接请求,为SMTP服务器保留的端口是25。
(2)客户端设置Winsock连接的IP地址或域名,指定端口号,主动发出连接请求,连接到SMTP服务器。比如,网易的SMTP服务器的域名是smtp.163.com,监听端口是25。
(3)服务器接收客户端的连接请求,并发回响应。客户端应收到类似220 BigFox ESMTP service ready这样的信息, 这就说明客户端已经与服务器建立TCP/IP连接,成功地实现了第一步。
(4)客户端和服务器分别向对方发送数据。
(5)客户端或服务器分别读取自己缓冲区中的数据。
(6)以上两步是SMTP会话的主要部分,要按照SMTP协议的规定,按照一定顺序,客户向服务器发送命令,服务器向客户发送应答,以上两步要多次重复。
(7)会话完毕,关闭客户端和服务器之间的连接。