




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、TCP/IP通信程序设计1、实验目的初步掌握C语言TCP/IP通信程序的设计。2、实验环境1、Windows 2000/NT/XP 操作系统。2、TCP/IP 协议。3、编程工具:Microsoft Visual C+ 2005。3、相关知识3.1 TCP/IP协议族表1 TCP/IP协议族应用层(FTP, DNS, HTTP, TELNET, SMTP 等)TCPUDPICMP IGMPIPARP RARP网络接口层TCP具有以下特点:1、面向连接。端到端的TCP连接会关注连接的状态,而网络的中间路由器只 关心IP分组的转发。2、可靠数据传递。TCP使用顺序号、采用直接应答方式,并在必要时通
2、过重 传来保证发自源端的数据能成功地被传递到目的地。3、流量控制。接收方向发送方发送一个接收窗口值,告诉发送方接收方能够 处理多少数据。在收到接收方发来的应答前,TCP发送方最多只能发送等于该窗口值的数据量。4、拥塞控制。用于防止TCP发送方发送的信息量超过网络中链路或路由器的 最大处理能力。流量控制和拥塞控制结合起来,使得TCP主机能迅速而公平地调整其发送速率,以达到与网络及接收方的处理能力相匹配3.2 端口与 Socket在进程通信的意义上,网络通信的最终地址不仅网络层提供的IP地址,还应包 括描述进程的协议端口( protocol port)。若没有端口,传输层就无法知道数据应当 交付给
3、应用层的哪个进程。因此,端口标示了应用层的进程。TCP和UDP分别提供了 216个不同的端口值。端口分为两类:1、周知端口(well-know port ),其值为0-1023 ,由ICANN负责分配(见 RFC 1700)。其中TCP和UDP均规定小于256的端口作为保留端口。2、临时端口,也称本地分配。进程需要访问传输服务时,向本地操作系统提 出动态申请,操作系统返回一个本地唯一的端口号,进程通过合适的系统调用将自 己和相应的端口号联系起来。Socket由4BSD UNIX首先提出,目的是解决网络通信问题。Socket的英文原义 是“插座",Socket与电话交换机的插座非常类似
4、,进程通信前,双方各创建一个 端点,每一个 Socket有一个本地唯一的 Socket号,由操作系统分配。Socket与IP 地址、IP地址的关系如图1所示。ip地址端口号Socket图1 Socket与IP地址、端口号由于TCP面向连接的特性,如果多台主机或一台主机的多个进程连接同一台服务器,则必须创建多个连接,如图 2所示。18/19端口80806C rj 9n9168I 一6端口8084端口8080端口8080图2与同一台主机建立三个连接TCP/IP标准指定了一个概念层接口,包含了一系列过程和函数。标准建议了每
5、 个过程和函数所需要的参数及其所执行操作的语义,但没有进一步指定数据表示的细节。详细的接口通常由操作系统来定义,只要完成TCP/IP标准中的功能,可以有不同的细节选择。这样,不同的操作系统的应用程序编程接口是各不相同的。例 如,广泛使用的 Berkeley Software Distribution UNIX 的 Socket接口、Windows 的 接口定义 Winsock、System V的接口定义TLI接口等。3.3 Socket的操作方式Socket有两种主要的操作方式:面向连接和面向无连接。面向连接的BSD UNIX Socket的工作流程如图3所示,而面向无连接的 BSD UNIX
6、 Socket的工作流程如图 4所示。到底用哪种模式是由应用程序的需要决定的。如果要求可靠性,用面向连接的 操作就会好一些。对于面向无连接的C/S模式,Socket不需要连接目的地的Socket, 它只是简单地投出数据报。无连接的操作简单高效,但数据的安全性不佳。服务器图3面向连接的C/S时序图服务器图4面向无连接的C/S时序图4、TCP通信程序设计4.1 编程要点由于TCP协议要求服务器和客户端建立连接,所以服务器需要通过Listen方法 监听客户端的请求。当客户端发出连接请求后,服务器在ConnectionRequest事件中调用Accept方法接受请求,从而与客户端建立连接。只有双方建立
7、连接后,才能进行数据的收发。如果在通信过程中任一方断开连 接,则通信过程终止。4.2 客户端程序客户端程序遵循以下步骤:1)建立客户端Socket连接。2)得到Socket读和写的流。3)操作流。4)关闭流。5)关闭 Socket。客户端的源程序代码如下:/ Module Name: Client.c/ Description:/This sample is the echo client. It connects to the TCP server,/sends data, and reads data back from the server./ Compile:/ cl -o Clien
8、t Client.c ws2_32.lib/ Command Line Options:/client -p:x -s:IP-n:x -o/-p:xRemote port to send to/-s:IPServer's IP address or hostname/-n:xNumber of times to send message/-oSend messages only; don't receive#include <winsock2.h>#include <stdio.h>#include <stdlib.h>#pragma com
9、ment(lib,"ws2_32")#define DEFAULT_COUNT#define DEFAULT_PORT#define DEFAULT_BUFFER#define DEFAULT_MESSAGE broadcasting system"2051502048"This is a test of the emergency char szServer128, szMessage1024;/ Server to connect to / Message to send to severintiPort = DEFAULT_PORT; / Port
10、 on server to connect toDWORD dwCount= DEFAULT_COUNT; Number of times to send messageBOOL bSendOnly = FALSE;/ Send data only; don't receive / Function: usage:/ Description:/ Print usage information and exit/void usage()printf("usage: client -p:x -s:IP-n:x -onn");printf("-p:xRemote
11、 port to send ton");printf("-s:IPServer's IP address or hostnamen");printf("-n:xNumber of times to send messagen");printf("-oSend messages only; don't receiven")ExitProcess;/ Function: ValidateArgs/ Description:/ Parse the command line arguments, and set so
12、me global flags/ to indicate what actions to perform/void ValidateArgs(intargc, char *argv)inti;for(i = 1; i <argc; i+) if (argvi0 = '-') II -岬='/')switch (tolower(argvi1) case 'p':/ Remote portif (strlen(argvi) > 3) iPort = atoi(&argvi3);break;case 's':/ Se
13、rverif (strlen(argvi) > 3) strcpy(szServer, &argvi3);break;case 'n':/ Number of times to send messageif (strlen(argvi) > 3)dwCount = atol(&argvi3);break;case 'o':/ Only send message; don't receivebSendOnly = TRUE;break;default: usage(); break; / Function: main/ Desc
14、ription:/ Main thread of execution. Initialize Winsock, parse the/ command line arguments, create a socket, connect to the/ server, and then send and receive data. /int main(intargc, char *argv) WSADATA wsd;SOCKET charsClient;szBufferDEFAULT_BUFFER;intret,i;structsockaddr_in server; structhostent *h
15、ost = NULL;/ Parse the command line and load Winsock /ValidateArgs(argc, argv);if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)printf("Failed to load Winsock library!n"); return 1;strcpy(szMessage, DEFAULT_MESSAGE); / Create the socket, and attempt to connect to the server /sClient = socket(A
16、F_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient = INVALID_SOCKET) printf("socket() failed: %dn", WSAGetLastError(); return 1;server.sin_family = AF_INET;server.sin_port = htons(iPort);server.sin_addr.s_addr = inet_addr(szServer);/ If the supplied server address wasn't in the form/ "
17、;aaa.bbb.ccc.ddd" it's a hostname, so try to resolve it/if (server.sin_addr.s_addr = INADDR_NONE) host = gethostbyname(szServer); if (host = NULL) printf("Unable to resolve server: %sn", szServer); return 1;CopyMemory(&server.sin_addr, host->h_addr_list0, host->h_length)
18、;if (connect(sClient, (structsockaddr *)&server, sizeof(server) = SOCKET_ERROR)printf("connect() failed: %dn", WSAGetLastError();return 1;/ Send and receive data/for(i = 0; i <dwCount; i+)ret = send(sClient, szMessage, strlen(szMessage), 0);if (ret = 0)break;else if (ret = SOCKET_ER
19、ROR)printf("send() failed: %dn", WSAGetLastError();break;printf("Send %d bytesn", ret);if (!bSendOnly)ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);if (ret = 0)/ Graceful closebreak;else if (ret = SOCKET_ERROR)printf("recv() failed: %dn", WSAGetLastError();break;szBu
20、fferret = '0'printf("RECV %d bytes: '%s'n", ret, szBuffer);closesocket(sClient);WSACleanup();return 0;下面解释与TCP套接字编程相关的内容。1、加载Winsock库WSAStartup(MAKEWORD(2,2), &wsd);其中,第一个参数是 Winsock的版本2.2,第二个参数接受返回的库版本信息。2、创建套接字socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);该调用要接收三个参数:af、ty
21、pe、protocol 0参数af指定通信发生的区域, UNIX 系统支持的地址族有: AF_UNIX AF_INET、AF_NS等,而 DOS WINDOWS 中仅支持AF_INET,它是网际网区域。因此,地址族与协议族相同。参数 type描 述要建立的套接字的类型。参数 protocol说明该套接字使用的特定协议,如果调用 者不希望特别指定使用的协议,则置为0,使用默认的连接模式。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此, socket()系统调用实际上指定了相关五元组中的“协议”这一元。3、建立套接字连接connect。用于建立连接。无连接的套
22、接字进程也可以调用 connect。,但这时在 进程之间没有实际的报文交换,调用将从本地操作系统直接返回。这样做的优点是 程序员不必为每一数据指定目的地址,而且如果收到的一个数据报,其目的端口未 与任何套接字建立“连接”,便能判断该端口不可操作。connect。的调用格式如下:connect(SOCKET s, conststructsockaddr FAR * name, intnamelen);参数s是欲建立连接的本地套接字描述符。参数name指出说明对方套接字地址结构的指针。对方套接字地址长度由namelen说明。如果没有错误发生,connect()返回0。否则返回SOCKET_ERRO
23、R在面向连接 的协议中,该调用导致本地系统和外部系统之间连接实际建立。由于地址族总被包含在套接字地址结构的前两个字节中,并通过socket()调用与某个协议族相关。因此bind()和connect()无须协议作为参数。4、数据传输-send()与recv()当一个连接建立以后,就可以传输数据了。常用的系统调用有send()和recv()。 send()调用用于在参数s指定的已连接的数据报或流套接字上发送输出数据, 格式如下:send(SOCKET s, const char FAR *buf, intlen, int flags);参数s为已连接的本地套接字描述符。buf指向存有发送数据的缓冲
24、区的指针, 其长度由len指定。flags指定传输控制方式,如是否发送带外数据等。如果没有错 误发生,send()返回总共发送的字节数。否则它返回 SOCKET_ERRORrecv()调用用于在参数s指定的已连接的数据报或流套接字上接收输入数据, 格式如下:recv(SOCKET s, char FAR *buf, intlen, int flags);参数s为已连接的套接字描述符。buf指向接收输入数据缓冲区的指针,其长 度由len指定。flags指定传输控制方式,如是否接收带外数据等。如果没有错误发 生,recv()返回总共接收的字节数。如果连接被关闭,返回0。否则它返回SOCKET_ER
25、RO R5、关闭套接字-closesocket()closesocket()关闭套接字s,并释放分配给该套接字的资源;如果s涉及一个打 开的TCP连接,则该连接被释放。closesocket()的调用格式如下: closesocket(SOCKET s);参数s待关闭的套接字描述符。如果没有错误发生,closesocket()返回0。否则 返回值 SOCKET_ERROR4.3服务器端程序服务器端程序遵循以下基本步骤:1)建立一个服务器Socket并开始监听。2)使用accept()取得新的连接。3)建立输入和输出流。4)在已有的协议上产生会话。5)关闭客户端流和Socket。6)关闭服务器S
26、ocketo服务器的处理过程是并发的,它为每个客户请求分配一个线程,而不是来一个 处理一个。所以看起来它在同时处理多个请求。服务器端的源程序代码如下:/ Module Name: Server.c/ Description:/ This example illustrates a simple TCP server that accepts/ incoming client connections. Once a client connection is/ established, a thread is spawned to read data from the/ client and ec
27、ho it back (if the echo option is not/ disabled)./ Compile:/ cl -o Server Server.c ws2_32.lib/ Command line options:/ server -p:x -i:IP-o/-p:x Port number to listen on/-i:str Interface to listen on/-oReceive only, don't echo the data back/#include <winsock2.h>#include <stdio.h>#inclu
28、de <stdlib.h>#pragma comment(lib,"ws2_32")#define DEFAULT_PORT5150#define DEFAULT_BUFFER4096intiPort = DEFAULT_PORT; Port to listen for clients on BOOL bInterface = FALSE, / Listen on the specified interface bRecvOnly = FALSE; / Receive data only; don't echo back char szAddress12
29、8;/ Interface to listen for clients on/ Function: usage/ Description:/ Print usage information and exit/void usage()printf("usage: server -p:x -i:IP-onn");printf("-p:x Port number to listen onn");printf("-i:strInterface to listen onn");printf("-oDon't echo the
30、data backnn");ExitProcess; / Function: ValidateArgs/ Description:/ Parse the command line arguments, and set some global flags / to indicate what actions to perform/void ValidateArgs(intargc, char *argv) int i;for(i = 1; i <argc; i+) if (argvi0 = '-') | (argvi0 = '/') switch
31、(tolower(argvi1) case 'p':iPort = atoi(&argvi3);break;case 'i': bInterface = TRUE; if (strlen(argvi) > 3) strcpy(szAddress, &argvi3);break;case 'o': bRecvOnly = TRUE; break; default: usage(); break; / Function: ClientThread/ Description:/ This function is called as
32、 a thread, and it handles a given/client connection. The parameter passed in is the socket/handle returned from an accept。call. This function reads/ data from the client and writes it back./DWORD WINAPI ClientThread(LPVOID lpParam) SOCKETsock=(SOCKET)lpParam;charszBuffDEFAULT_BUFFER;intret,nLeft, id
33、x;while(1)/ Perform a blocking recv() call/ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);if (ret = 0)/ Graceful closebreak;else if (ret = SOCKET_ERROR) printf("recv() failed: %dn", WSAGetLastError(); break;szBuffret = '0'printf("RECV: '%s''n", szBuff);/ If we se
34、lected to echo the data back, do it/if (!bRecvOnly) nLeft = ret;idx = 0;/ Make sure we write all the data/while(nLeft> 0)ret = send(sock, &szBuffidx, nLeft, 0);if (ret = 0) break;else if (ret = SOCKET_ERROR)printf("send() failed: %dn", WSAGetLastError();break;nLeft -= ret;idx += ret
35、;return 0;/ Function: main/ Description:/ Main thread of execution. Initialize Winsock, parse the/ command line arguments, create the listening socket, bind / to the local address, and wait for client connections./int main(intargc, char *argv)WSADATA wsd;SOCKETsListen,sClient; intiAddrSize;HANDLEhTh
36、read;DWORDdwThreadId;structsockaddr_in local, client;ValidateArgs(argc, argv);if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)printf("Failed to load Winsock!n");return 1;/ Create our listening socket/sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);if (sListen = SOCKET_ERROR)printf("so
37、cket() failed: %dn", WSAGetLastError();return 1;/ Select the local interface and bind to it/if (bInterface)local.sin_addr.s_addr = inet_addr(szAddress);if (local.sin_addr.s_addr = INADDR_NONE) usage();elselocal.sin_addr.s_addr = htonl(INADDR_ANY);local.sin_family = AF_INET;local.sin_port = hton
38、s(iPort);if (bind(sListen, (structsockaddr *)&local, sizeof(local) = SOCKET_ERROR)printf("bind() failed: %dn", WSAGetLastError();return 1;listen(sListen, 8);/ In a continous loop, wait for incoming clients. Once one/ is detected, create a thread and pass the handle off to it./while (1)
39、iAddrSize = sizeof(client);sClient = accept(sListen, (structsockaddr *)&client, &iAddrSize);if (sClient = INVALID_SOCKET)printf("accept() failed: %dn", WSAGetLastError();break;printf(" Accepted client: %s:%dn",inet_ntoa(client.sin_addr), ntohs(client.sin_port);hThread = C
40、reateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId);if (hThread = NULL)printf("CreateThread() failed: %dn", GetLastError();break;CloseHandle(hThread);closesocket(sListen);WSACleanup();return 0;与客户端程序相比,服务器端在以下几个方面存在差异。1、指定本地地址bind()当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被
41、命名。 bind()将套接字地址(包括本地主机地址和本地端口地址)与所创建的套接字号联 系起来,即将名字赋予套接字,以指定本地半相关。其调用格式如下:bind(SOCKET s, conststructsockaddr FAR * name, intnamelen);参数s是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。参数 name是赋给套接字s的本地地址(名字),其长度可变,结构随通信域的不同而不 同。namelen 表明了 name 的长度。如果没有错误发生,bind()返回0。否则返回值SOCKET_ERROR地址在建立套接字通信过程中起着重要作用,作为一个网络应用程序设计者对 套接字地址结构必须有明确认识。例如,UNIX BSD有一组描述套接字地址的数据结构,其中使用TCP/IP协议的地址结构为:structsockaddr_inshortsin_family; /*AF_INET*/u_shortsin_port; /*16 位端口号,网络字节顺序 */structin_addrsin_addr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 疫情教育主题班会课件
- 2025版知识产权侵权纠纷调解合同公证书范本示例
- 二零二五版建筑废弃物回收利用合同样本
- 2025年度养殖场养殖技术培训合同
- 疫情家国情怀班会课件
- 电商平台用户注册协议及使用规范
- 六年级写人作文爷爷550字(11篇)
- 疏散演练学生安全课件
- 监利县小升初数学试卷
- 广州市重点小学数学试卷
- 2025枣庄机场建设投资有限公司招聘(110人)笔试参考题库附带答案详解版
- 国际压力性损伤溃疡预防和治疗临床指南(2025年版)解读
- 2024陕西延长石油物流集团有限公司社会招聘笔试参考题库附带答案详解
- 检验检测机构质量管理课件
- 讲课儿童肺功能详解课件
- 沙迪克操作手册
- 不宜流通人民币硬币宣贯材料课件
- 小学升初中入学测试宁外入学试卷2
- 协和精神课件
- 儿童保健规范化门诊标准(2021年版)
- 检验科危化品安全数据表完整
评论
0/150
提交评论