




已阅读5页,还剩627页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
此文档收集于网络,如有侵权,请联系网站删除第1章 客户机/服务器开发本章主要向读者介绍使用Winsock 开发典型客户机/服务器程序的方法。本章精选了5 个实例程序从易到难,包括TCP客户机/服务器程序、多线程TCP服务器、通过Internet传输文件,以及时间协议的具体应用。1.1 Winsock 编程入门简单的TCP 服务器本节通过一个简单的TCP 服务器实例来讲述基本的Winsock 编程。实例程序在配套光盘的SimpleTcpServerSrc工程下。1.1.1 Winsock编程简介Winsock 是Windows 下网络编程的标准接口,它允许两个或多个应用程序在同一台电脑上,或者是通过网络相互交流。Winsock是真正的协议无关的接口,本节详细介绍Winsock编程的方法。如果仅有一台电脑,也仍然能够进行Winsock 编程。可以使用本地回环地址。这样的话,如果有一个TCP 服务器运行在你的电脑上,那么运行在此电脑上的客户程序使用这个回环地址,即可连接到服务器。1.1.2 简单的TCP服务器下面一步步创建简单的TCP 服务器。在此之前,还要做下面这些准备工作,以便可以真正的进行Winsock编程。l 使用VC+ 6.0 App Wizard创建一个Win32控制台应用程序。l 记住要设置选项,以便添加对MFC的支持。l 打开文件stdafx.h,添加语句:#include 。l 在winsock2.h之后,还要包含conio.h和iostream.h。l 打开菜单ProjectSettings,切换到Link选项卡,向库模块列表中添加ws2_32.lib。或者,直接在代码中添加语句:#pragma comment(lib, WS2_32),以便链接到WS2_32.DLL库。因为所有的Winsock函数都是从WS2_32.DLL导出的。1. main 函数在main 函数中启动一个线程,然后循环调用_getch()。_getch()仅简单地等待键盘输入,返回被按键的ASCII值。ESCAPE 键的ASCII值是27,所以函数返回27 后,程序才退出循环。当main函数返回,进程将终止,进程内的线程也将会终止。上述过程的具体程序代码如下。int _tmain(int argc, TCHAR* argv, TCHAR* envp)Visual C+网络程序设计实例详解2int nRetCode = 0;cout Press ESCAPE to terminate programrn;AfxBeginThread(ServerThread,0);while(_getch()!=27);return nRetCode;2. ServerThread函数下面要做的是列出ServerThread函数的实现代码,使用注释来解释每行代码的作用。TCP服务器启动之后在端口20248监听。当有客户连接时,服务器向客户发回一个消息,告诉客户自己的IP 地址,然后关闭连接,并继续到端口20248 去接受连接。上述过程的具体程序代码如下。UINT ServerThread(LPVOID pParam)cout Starting up TCP serverrn;/ SOCKET实际上是一个unsigned int类型SOCKET server;/ WSADATA结构将有WSAStartup函数来填充WSADATA wsaData;/ 对TCP/IP 套接字来说,sockaddr_in结构指定了套接字的地址/ 其他协议使用相似的结构sockaddr_in local;/ WSAStartup函数负责加载Winsock库的函数/ 第一个参数用来指定想要加载的Winsock库的版本int wsaret=WSAStartup(0x101,&wsaData);/ 调用成功,WSAStartup函数返回0/ 失败的话,程序就退出if(wsaret!=0)return 0;/ 现在我们填充sockaddr_in结构local.sin_family=AF_INET; / 地址家族Address familylocal.sin_addr.s_addr=INADDR_ANY; / 要求使用当前主机配置的所有IP地址local.sin_port=htons(u_short)20248); / 使用的端口/ socket函数用来创建我们的SOCKETserver=socket(AF_INET,SOCK_STREAM,0);/ 如果socket()函数调用失败,我们退出第1章 客户机/服务器开发3if(server=INVALID_SOCKET)return 0;/ 为套接字关联本地地址的函数是bind.。/ bind函数用在没有建立连接的套接字上,它的作用是绑定面向连接的或者无连接的套接字。/ 套接字被socket函数创建以后,存在于指定的地址家族里,但它是未命名的。/ bind函数通过安排一个本地名称到未命名的socket建立此socket的本地关联。/ 本地名称包含3个部分:主机地址、协议号(分别为UDP或TCP)和端口号。if(bind(server,(sockaddr*)&local,sizeof(local)!=0)return 0;/ listen函数设置套接字进入监听状态/ 为了接受连接,首先使用socket函数创建一个套接字,然后使用bind函数将它绑定到一个本地地址,/ 再用listen函数为到达的连接指定一个backlog,最后使用accept接受请求的连接。/ 函数的第二个参数是backlog值if(listen(server,10)!=0)return 0;/ 我们需要变量保存客户套接字,下面是这些变量的定义SOCKET client;sockaddr_in from;int fromlen=sizeof(from);/ 下面进入无限循环while(true)char temp512;/ accept() 将接受到了的客户连接client=accept(server,(struct sockaddr*)&from,&fromlen);sprintf(temp,Your IP is %srn,inet_ntoa(from.sin_addr);/ 我们简单地将这串字符发送给客户send(client,temp,strlen(temp),0);cout Connection from inet_ntoa(from.sin_addr) serverPress ESCAPE to terminate programStarting up TCP serverConnection from 22Connection from E:workServerDebug下面是客户端的输出:nishsumida:$ telnet 8 20248Trying 8.Connected to 8.Escape character is .Your IP is 22Connection closed by foreign host.nishsumida:$1.2 Winsock 编程入门简单的TCP 客户端本节讲述如何编写TCP 客户端程序。本节的实例程序将连接到HTTP 服务器,获取一个文件。实例程序在配套光盘的SimpleTcpClientSrc工程下,运行效果如图1.1 所示。图1.1 TCP客户端运行效果第1章 客户机/服务器开发51.2.1 TCP客户程序的编写流程下面先介绍TCP客户程序的编写流程,然后再详细讨论每一步的具体实现。(1)使用WSAStartup()初始化Winsock库。(2)使用socket()创建一个IPPROTO_TCP类型的套接字。(3)使用gethostbyname()/gethostbyaddr()获取主机信息。(4)使用connect()连接到服务器。(5)使用send()/recv()发送和接收数据,直到TCP通信结束。(6)使用closesocket()关闭套接字连接。(7)使用WSACleanup()释放Winsock库。1.2.2 初始化Winsock库和其他所有的Winsock 程序一样,首先初始化Winsock 库。这也是检查Winsock 在该系统上是否可用的一种方法。int wsaret=WSAStartup(0x101,&wsaData);if(wsaret)return;1.2.3 创建套接字套接字是在客户和服务器之间通信的实体。当客户连接到服务器时,就会有两个套接字:客户方套接字和对应的服务器端套接字,这里将他们称作CLIENTSOCK 和SERVERSOCK。当客户方在CLIENTSOCK 使用send()函数时,服务器方可以在SERVERSOCK 上使用recv()函数来获取客户发送的数据。反之亦然。以下是创建套接字的代码。SOCKET conn;conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(conn=INVALID_SOCKET)return;1.2.4 获取主机信息在连接到主机(服务器)之前,必须首先获取主机的信息。可以使用两个函数:gethostbyname()和gethostbyaddr()。如果有服务器的DNS 名称(例如, 或),要使用gethostbyname()函数;当我们有服务器实际的IP 地址(例如,或者00),要使用gethostbyaddr()函数。为了方便使用,既允许用户输入DNS名称,也允许用户输入IP地址。程序中对用户的输入调用了inet_addr()函数,此函数将IP 地址转换为标准的网络地址格式。如果该函数返回失败,说明用户输入的不是IP地址,反之,说明用户输入了有效的IP地址。此过程的具体实现代码如下。if(inet_addr(servername)=INADDR_NONE)hp=gethostbyname(servername);Visual C+网络程序设计实例详解6elseaddr=inet_addr(servername);hp=gethostbyaddr(char*)&addr,sizeof(addr),AF_INET);if(hp=NULL)closesocket(conn);return;1.2.5 连接到服务器connect()函数用来和目的服务器建立连接。参数为已创建的套接字和一个包含服务器地址信息的sockaddr 结构。sockaddr 结构中的主机地址用gethostbyname()/gethostbyaddr()的返回值来填充,同时也要指定一个有效的端口号。具体程序代码如下。server.sin_addr.s_addr=*(unsigned long*)hp-h_addr);server.sin_family=AF_INET;server.sin_port=htons(80);if(connect(conn,(struct sockaddr*)&server,sizeof(server)closesocket(conn);return;1.2.6 TCP通信套接字连接建立之后,客户和服务器可以使用send()和recv()函数交换数据。这个过程一般称作TCP通信。本节的例子中,我们需要HTTP通信,这比其他协议(如SMTP或POP3)简单多了。HTTP GET 命令从HTTP 服务器获取文件,可以是HTML 文件、图像文件、MP3等。GET命令的使用格式如下(这里是最简单的情况):GET http-path-to-filernrn具体地使用如下代码发送GET命令。sprintf(buff,GET %srnrn,filepath);send(conn,buff,strlen(buff),0);服务器接收到此命令,就开始向客户发送指定的文件。正如使用send()发送命令一样,程序使用recv()接收服务器发来的数据。下面是接收数据的程序代码。循环调用recv()函数,直到它返回0 为止。recv()函数返回0 说明服务器已经完成了数据的发送。程序将接收到的数据写入到文件中。while(y=recv(conn,buff,512,0)第1章 客户机/服务器开发7f.Write(buff,y);1.2.7 关闭连接、释放Winsock库数据传输完毕之后,必须关闭连接。本例中,HTTP连接是由服务器端在传输完文件之后关闭的,客户端也要关闭套接字,释放资源。在更加复杂的程序中,通常在调用closesocket()之前先调用shutdown()函数,以确保缓冲区中的数据传输完毕。下面是关闭连接的程序代码。closesocket(conn);最后,还要调用WSACleanup()释放Winsock库,代码如下所示。WSACleanup();1.3 多线程TCP 服务器和客户端实例本节的实例是一个多线程的TCP文件服务器,它使用自定义通信协议向客户方传递文件。实例程序保存在配套光盘的MTSClientSrc(客户端)和MTServerSrc(服务器端)工程下。1.3.1 实例介绍1.1 节讲述的TCP服务器在同一时刻仅能接收一个连接。我们知道,一个服务器程序必须能够在任何时间处理多个客户连接。本节将写一个多线程TCP 服务器。并且还将创建自定义的基于TCP 的通信协议。还要编写一个客户端程序,它将连接到服务器,使用该自定义协议与服务器通信。服务器程序的功能是向客户程序发送请求的文件,客户程序将这个文件保存到本地计算机中。这里使用的处理多个客户的方法是最原始的一个客户连接一个线程的方法。有许多其他更加有效的处理多个连接的机制,如I/O 完成端口模型等。但是,如果通信协议比较简单,每个客户连接对速度要求并不太苛刻的话,使用本节的方法还是很合理的,除非同一时间连接的客户数量特别巨大。对这方面的内容感兴趣的读者可以参考Windows 网络与通信程序设计一书(人民邮电出版社出版)。1.3.2 多线程服务器在main()函数中,本节例子的代码和前面的TCP 服务器没有太大的不同,都是先启动服务器线程,然后循环调用_getch()函数,直到用户按下ESC键。具体代码如下:int _tmain(int argc, TCHAR* argv, TCHAR* envp)int nRetCode = 0;cout Press ESCAPE to terminate programrn;AfxBeginThread(MTServerThread,0);while(_getch()!=27);Visual C+网络程序设计实例详解8closesocket(server);WSACleanup();return nRetCode;下面集中精力研究服务器线程。在服务器线程中,直到调用listen()为止,程序代码都与1.1 节的服务器程序完全相同。在调用accept()部分我们做了一些微小的改动,代码如下所示。UINT MTServerThread(LPVOID pParam)/* 这里的代码被省略了*/if(listen(server,10)!=0)return 0;SOCKET client;sockaddr_in from;int fromlen=sizeof(from);while(true)client=accept(server,(struct sockaddr*)&from,&fromlen);AfxBeginThread(ClientThread,(LPVOID)client);return 0;MTServerThread 接收到连接后,启动一个新的线程来处理这个连接,并将客户的套接字句柄传递给新的线程,然后再返回继续调用accept()。这样,客户连接的时候,一个新的线程就会启动来处理这个客户的I/O 请求,再有客户连接的时候,又会创建一个新的线程,如此反复下去。1.3.3 自定义传输协议为了实施文件传输,必须首先定义一个简单的协议,下面来定义这个协议使用的命令。显然需要一个命令来关闭会话,这个命令是“QUIT”。因为不想每个人都可以下载文件,所以添加“AUTH”命令,此命令的参数用来指定密码。如果密码正确,我们就将用户设为授权状态。AUTH 和QUIT 命令都可以在未授权状态使用。但是用来获取文件的命令“FILE”仅允许在授权状态使用。总结一下,共定义了如下3 个命令。l QUIT:此命令将关闭连接。l AUTH password:此命令将使用户进入授权状态。第1章 客户机/服务器开发9l FILE filename with full path:获取指定文件(仅在授权状态才可用)。为了说明自定义协议是如何工作的,使用#来表示成功的消息,使用!来表示错误消息,下面完整地显示了一个TCP会话过程(在客户端看来)。Trying 4.Connected to 4.Escape character is .#Server Ready.file c:config.sys!You are not logged in.auth yellow!Bad password.auth passwd#You are logged in.file c:config.sysDEVICE=C:WINDOWSHIMEM.SYSDEVICE=C:WINDOWSEMM386.EXE#File c:config.sys sent successfully.file c:setup.logInstallShield SilentVersion=v6.00.000File=Log FileResponseResultResultCode=0ApplicationName=Intel Ultra ATA Storage DriverVersion=6.03.007Company=IntelLang=0009#File c:setup.log sent successfully.file d:g5.doc!File d:g5.doc could not be opened.quitConnection closed by foreign host.可以看到,用户登录之后,他可以请求任意数量的文件。文本文件和二进制文件均可。这些命令的具体实现是在ClientThread线程函数中进行的,下面是具体程序代码。UINT ClientThread(LPVOID pParam)Visual C+网络程序设计实例详解10char buff512;CString cmd;CString params;int n;int x;BOOL auth=false;SOCKET client=(SOCKET)pParam;strcpy(buff,#Server Ready.rn);send(client,buff,strlen(buff),0);while(true)n=recv(client,buff,512,0);if(n=SOCKET_ERROR )break;buffn=0;if(ParseCmd(buff,cmd,params)if(cmd=QUIT)break;if(cmd=AUTH)if(params=passwd)auth=true;strcpy(buff,#You are logged in.rn);elsestrcpy(buff,!Bad password.rn);send(client,buff,strlen(buff),0);if(cmd=FILE)if(auth)if(SendFile(client,params)sprintf(buff,#File %s sent successfully.rn,params);第1章 客户机/服务器开发11elsesprintf(buff,!File %s could not be opened.rn,params);x = send(client, buff, trlen(buff),0);elsestrcpy(buff,!You are not logged in.rn);send(client,buff,strlen(buff),0);elsestrcpy(buff,!Invalid command.rn);send(client,buff,strlen(buff),0);closesocket(client);return 0;程序首先向客户发送欢迎信息,接着就进入循环,接收命令。程序使用自定义函数ParseCmd来解析命令字符串,将字符串中的命令保存到一个CString对象中,将命令的参数保存到另一个CString 对象中。如果ParseCmd返回false,则意味着客户发送了一个未知命令,服务器程序就返回一个错误消息。如果命令是QUIT,程序就离开循环,关闭客户套接字,退出这个线程。程序也有一个布尔类型的标志auth,仅当客户经授权后才将此标志设为true。auth 为false 的情况下,如果程序接收到一个FILE 命令,就会返回一个错误消息,说明客户还没有登录。这里使用了硬编码“passwd”作为密码,但是在真实的世界里,用户名/密码应该从数据库或者配置文件获取。使用AUTH 命令用户可以登录到服务器。成功登录后,它们便可获取文件了。程序使用自定义函数SendFile通过TCP连接向客户发送文件。下面是解析命令字符串的ParseCmd函数的实现代码。BOOL ParseCmd(char *str, CString& cmd, CString& params)int n;CString tmp=str;tmp.TrimLeft();tmp.TrimRight();if(n=tmp.Find( )=-1)Visual C+网络程序设计实例详解12tmp.MakeUpper();if(tmp!=QUIT)return false;cmd=tmp;return true;cmd=tmp.Left(n);params=tmp.Mid(n+1);cmd.MakeUpper();if(cmd!=AUTH) & (cmd!=FILE)return false;return true;此函数分离字符串,如果遇到一个有效的命令就返回true,否则返回false来指示错误。下面是发送文件的SendFile函数的实现代码。BOOL SendFile(SOCKET s, CString fname) CFile f;BOOL p=f.Open(fname,CFile:modeRead);char buff1024;int y;int x;if(!p)return false;while(true) y=f.Read(buff,1024);x=send(s,buff,y,0);if(y1024)f.Close();break;return true;如果文件发送成功,SendFile()返回true,如果找不到文件,SendFile()返回false。1.3.4 客户端程序客户端程序在配套光盘的MTSClientSrc 的工程下,此程序的大体思路与1.2 节的TCP 客户程序基本相同,这里就不再重复了。但是仍然有几点需要指出,不要在recv()返回的缓冲区第1章 客户机/服务器开发13上使用字符串操作函数,如strcpy()和strchr()等,因为这些字节缓冲区也许不是以NULL结尾的。下面是客户端程序的主要实现代码。int EndFile(char *buff, int len) ; / 两个帮助函数,用来检查文件传输是否完毕,服务器上是否有指定文件int NoFile(char *buff, int len) ;using namespace std;int _tmain(int argc, TCHAR* argv, TCHAR* envp)const char* servername=;if(argc2)cout h_addr);Visual C+网络程序设计实例详解14server.sin_family=AF_INET;server.sin_port=htons(20248);if(connect(conn,(struct sockaddr*)&server,sizeof(server)closesocket(conn);return 0;char buff512;int z;z=recv(conn,buff,512,0);buffz=0;strcpy(buff,auth passwdrn);send(conn,buff,strlen(buff),0);z=recv(conn,buff,512,0);buffz=0;for(int j=1;jargc;j+)sprintf(buff,file %srn,argvj);send(conn,buff,strlen(buff),0);CFile f;char *fname;char fname2256;if(!(fname=strrchr(argvj,)strcpy(fname2,argvj);elsestrcpy(fname2,fname+1);f.Open(fname2,CFile:modeCreate | CFile:modeWrite);bool first=true;bool second=false;while(true)z=recv(conn,buff,128,0);if(z=SOCKET_ERROR)cout rnrnsocket error socket error socket errorrn;break;if(second)第1章 客户机/服务器开发15if(NoFile(buff,128)128)cout File argvj not found on serverrn;break;second=false;if(first)if(NoFile(buff,128)128)cout File argvj not found on serverrn;break;first=false;second=true;int b;if(b=EndFile(buff,z)z)f.Write(buff,b);cout fname2 has been saved.rn;break;f.Write(buff,z);f.Close();closesocket(conn);WSACleanup();return 0;int EndFile(char *buff, int len) / 用来检查文件传输是否完毕int pos=len;for(int u=0;u(len-4);u+)if(buffu=#)if(buffu+1=F)Visual C+网络程序设计实例详解16if(buffu+2=i)if(buffu+3=l)if(buffu+4=e)pos=u;break;return pos;int NoFile(char *buff, int len) / 用来检查服务器上是否有指定文件int pos=len;for(int u=0;umtsclientUsage :- mtsclient file1 file2 file3 .E:workMTSClientDebugmtsclient c:cu.gif c:cp.gif c:g.gif c:dddFile c:cu.gif not found on servercp.gif has been saved.g.gif has been saved.File c:ddd not found on serverE:workMTSClientDebug第1章 客户机/服务器开发171.4 网络对时程序实例网络对时也就是从Internet上获得准确的时间,以此来校对本地计算机时钟。通过本节的实例程序,大家可以了解到协议和Winsock 函数的具体应用。实例程序保存在配套光盘的NetTime工程下。1.4.1 时间协议(Time Protocol)Time Protocol (RFC-868)是一种非常简单的应用层协议。它返回一个未格式化的32 位二进制数字,这个数字描述了从1900 年1 月1 日午夜到现在的秒数。服务器在端口号37 监听时间协议请求,以TCP/IP 或者UDP/IP 格式返回响应。将服务器的返回值转化成本地时间是客户端程序的责任(进行转化时需要借用文件时间,详见后面的程序代码)。下面是在传输层使用TCP的Time Protocol的工作过程(这里S代表服务器,C代表客户):S: 监听端口37C: 连接到端口37S: 以32 位二进制数发送时间C: 接收时间C: 关闭连接S: 关闭连接如果服务器不能决定现在是什么时间,服务器会拒绝连接或不发送任何数据而直接关闭连接。1.4.2 TCP/IP实现代码下面是使用Time Protocol实现的基于TCP/IP的网络对时程序。程序运行后,自动使本地时间和时间服务器时间同步,这里使用的时间服务器是1,更多的服务器地址在“/service/time-servers.html”网站列出(如8、01 等)。void SetTimeFromTP(ULONG ulTime) / 根据时间协议返回的时间设置系统时间/ Windows文件时间是一个64位的值,它是从1601年1月1日中午12:00到现在的时间间隔,/ 单位是1/1000 0000秒,即1000万分之1秒(100-nanosecond )FILETIME ft;SYSTEMTIME st;/ 首先将基准时间(1900年1月1日0点0分0秒0毫秒)转化为Windows文件时间st.wYear = 1900;st.wMonth = 1;st.wDay = 1;st.wHour = 0;st.wMinute = 0;st.wSecond = 0;st.wMilliseconds = 0;Visual C+网络程序设计实例详解18SystemTimeToFileTime(&st, &ft);/ 然后将Time Protocol使用的基准时间加上以及逝去的时间,即ulTimeLONGLONG *pLLong = (LONGLONG *)&ft;/ 注意,文件时间单位是1/1000 0000秒,即1000万分之1秒(100-nanosecond )*pLLong += (LONGLONG)10000000 * ulTime;/ 再将时间转化回来,更新系统时间FileTimeToSystemTime(&ft, &st);SetSystemTime(&st);int main()/ . 省略了调用WSAStartup的初始化代码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(37);/ 这里使用的时间服务器是1,更多地址请参考/service/its.htmservAddr.sin_addr.S_un.S_addr = inet_addr(1);if(:connect(s, (sockaddr*)&servAddr, sizeof(servAddr) = -1)printf( Failed connect() n);return 0;/ 等待接收时间协议返回的时间。学习了Winsock I/O模型之后,最好使用异步I/O,以便设置超时ULONG ulTime = 0;int nRecv = :recv(s, (char*)&ulTime, sizeof(ulTime), 0);if(nRecv 0)ulTime = ntohl(ulTime);SetTimeFromTP(ulTime);printf( 成功与时间服务器的时间同步!n);else第1章 客户机/服务器开发19printf( 时间服务器不能确定当前时间!n);:closesocket(s);return 0;1.5 网络文件传输实例本节的实例程序说明了如何使用MFC中的CSocket 类将文件(大文件或者小文件)通过网络从一个计算机传输到另一个计算机。实例程序保存在配套光盘的TransferFiles_demo 工程下,运行效果如图1.2 所示。图1.2 文件传输程序运行效果使用CSocket类传输文件并不困难,但是也很容易出错。最经常犯的错误之一是不能正确处理各种CSocket成员函数的返回值。这可能是由于没能理解套接字的工作原理所致。大多数初学者将套接字看作管道,在这个管道里面将信息从一方推向另一方。这种看法并不是完全错误的,因为流套接字会保证信息将以正确的顺序传递到目的地。但是可能会出现套接字接收不到信息的情况。同样地,虽然套接字接收到的所有信息都将被传入网络,但是并没有一一对应的对CSocket:Send()(发送方)和CSocket:Receive()(接收方)的调用。例如,如果调用CSocket:Send()发送了10个字节,那么在另一方调用CSocket:Receive()就可能收到10个字节,或者仅收到1 个字节,或者这两者之间的其他个数。结果,接收方就可能需要多次调用Visual C+网络程序设计实例详解20CSocket:Receive()才行。除了上述问题,事实上在套接字通信期间任何事都可能发生错误。例如,客户也许断开连接,服务器也许超时,网络电缆也许断开等。所有的CSocket函数都通过返回值说明了具体执行情况。成功传输文件的关键所在就是仔细检查每个调用的返回值。1.5.1 服务器端程序代码分析下面开始介绍具体的程序代码,然后再解释每一部分的作用。下面是从服务器向客户端发送文件的程序代码。#define PRE_AGREED_PORT 8686#define SEND_BUFFER_SIZE 4096BOOL CYourServerClass:SendFileToRemoteRecipient(CString fName)/*/ listens for a connection from a remote client and uploads a file to it / 创建套接字,监听客户连接/ the remote client must be running/ a counterpart GetFileFromRemoteSender function/ Input: CString fName = name of local file/ which will be uploaded to remote client/ Output: BOOL return value indicates success or failure of the upload*/ create socket and listen on pre-designated port/ AfxSocketInit(NULL);/ make certain this is done somewhere in each thread/ (usually in InitInstance for main thread)CSocket s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 深度学习 课件 第2章 卷积神经网络
- 聚焦未来2025年公共关系学考试试题及答案
- 直观理解市政工程考试案例的试题及答案
- 项目启动会议的试题及答案
- 印刷及广告宣传品制作合同
- 水文分析工具及其应用试题及答案
- 猪场规划设计要点
- 专科内科考试试题及答案
- 经济法概论考试重难点梳理试题及答案
- 市政工程考试环境评价内容要点及试题及答案
- 超职数配备干部整改方案
- 中药材、中药饮片分类贮存常温库货品名称目录
- 中考模拟考试实施方案
- (部编版)统编版小学语文教材目录(一至六年级上册下册齐全)
- 四川省南充市2023-2024学年六年级下学期期末英语试卷
- 智能化完整系统工程竣工验收资料标准模板
- 《当呼吸化为空气》读书分享
- 广东省江门市语文小升初试卷与参考答案(2024-2025学年)
- 阀体结构优化设计提升截止阀可靠性
- 常压储罐管理制度
- Unit1 Making friends part B How can we be a good friend(教学设计)-2024-2025学年人教PEP版(2024)英语三年级上册
评论
0/150
提交评论