• 回答数

    4

  • 浏览数

    142

hellosnow.
首页 > 考试培训 > 培训网络编程

4个回答 默认排序
  • 默认排序
  • 按时间排序

KauluwehiS

已采纳

参考课程:《Windows网络编程技术》(推荐指数:五星)中文版高清PDF格式 486页 ,极力推荐,含目录书签,是一本内容丰富,讲解详细的Windows网编。《TCP/IP详解》共三卷,《TCP/IP详解卷1:协议》描述了属于每一层的各个协议以及它们如何在不同操作系统中运行。作者LawrenceBerkeley实验室的tcpdump程序来捕获不同操作系统和TCP/IP实现之间传输的不同分组。对tcpdump输出的研究可以帮助理解不同协议如何工作。《C++网络编程 卷1》 《C++网络编程,卷2》 本书将向你描述这些框架的设计,以及它们可怎样帮助你克服较低级的本地操作系统API与较高级的分布式计算中间的各种局限,高效地开发出高质量、可移植的C++网络化应用。《Unix网络编程》本书是一部UNIX网络编程的经典之作。附录中给出了测量各种IPC形式性能的方法。本书内容详尽且具权威性,几乎每章都提供精选的习题,并提供了部分习题的答案,是网络研究和开发人员理想的参考书。

培训网络编程

99 评论(11)

听雨9014

我们在前几期的文章中曾经给大家简单介绍了关于网络编程中不同协议的使用情况与运行的原理问题。今天北京IT培训就继续来了解一下,关于网络编程中不同协议的状态连接问题。

1、为什么建立连接协议是三次握手,而关闭连接是四次挥手呢?

这是因为服务端的LISTEN状态下的SOCKET收到SYN的请求连接时,可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里一起发送.但是关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送了,但是另一方未必所有的数据都全部发送完全了,所以可能不会立马关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方表示你同意现在关闭连接了,所以这里的

2、ACK报文和FIN报文是分开发送的.

为什么不能用两次握手进行连接?

在三次握手中,总共需要完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已经准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认.

现在把三次握手改成仅需要两次握手,是可能会发生死锁的.考虑计算机客户端和服务端之间的通信,假定客户端给服务端发送一个连接请求分组,服务端收到了这个分组,并发送了确认应答分组.按照两次握手的协定,服务端认为链接已经成功的建立了,可以开始发送数据分组.可是,客户端在服务端的应答分组在传输中被丢失的情况下,将不会知道服务端是否已准备好,不知道服务端建立什么样的序列号,客户端甚至会怀疑服务端是否收到自己的连接请求分组.在这种情况下,客户端认为连接还未建立成功,将忽略服务端发来的任何数据分组,只等待连接确认应答分组.而服务端在发出的数据分组超时后,重复发送同样的数据分组,就形成了死锁.

3、为什么TIME_WAIT状态需要等2MSL后才能返回到CLOSED状态?

什么是MSL?MSL即MaximumSegmentLifetime,也就是报文大生存时间.'MSL是任何报文段被丢弃前在网络内的长时间.'那么,2MSL也就是这个时间的两倍,当TCP连接完成四个报文段的交换时,主动关闭的一方将继续等待一定时间(2-4)分钟,即使两端的应用程序结束.

4、为什么需要2MSL呢.

一,虽然双方都同意关闭连接了,而且握手的四个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文.

二,报文可能会被混淆,意思是说其他时候的连接可能会被当做本次的连接.

当某个连接的一端处于TIME_WAIT状态时,该连接将不能再被使用.事实上,对于我们比较有现实意义的是,这个端口将不能再被使用.某个端口处于TIME_WAIT(其实应该是这个连接)状态时,这意味着这个TCP连接并没有断开(完全断开),那么.如果你bind这个端口,就会失败.对于服务器而言,如果服务器突然crash掉了,那么他将无法在2MSL内重新启动,因为bind会失败.解决这个问题的一个方法就是设置SOCKET的SO_REUSEADDR选项.这个选项意味着可以重用一个地址.

当建立一个TCP连接时,服务端会继续用原有端口,同时用这个端口与客户端通信.而客户端默认情况下会使用一个随机端口与服务端的端口通信.有时候,为了服务端的安全性,我们需要对客户端进行验证,即限定某个IP的某个特定端口的客户端.客户端可以使用bind来使用特定的端口.对于服务端,当设置了SO_REUSEADDR选项时,它可以在2MSL内启动并listen成功.但是对于客户端,当使用bind并设置SO_REUSEADDR时,如果在2MSL内启动,虽然bind会成功,但是在windows平台上connect会失败.而在linux是哪个不存在这个问题.

205 评论(12)

刘李铭俊521

新手必学:windows网络编程经典入门作者:huyoo对于一个windows网络编程初学者,下面方法是经典入门。 初学者建议不要用MFC提供的类,而用windows API做一个简单服务器和客户端,这样有助于对socket编程机制的理解。 为了简单起见,应用程序是基于MFC的标准对话框。Winsock用WINDOWS API实现: (1)服务器端有两个线程: 主线程 — 你需要编写以下函数来实现 #define NETWORK_EVENT USER_MESSAGE+100 file://定义网络事件 sockaddr_in clientaddr; file://暂时存放客户端IP地址 file://自己定义消息映射函数,将上面定义的网络事件映射到处理函数 为网络事件处理函数,它在下面定义 ON_MESSAGE(NETWORK_EVENT, OnNetEvent); 在你对话框中的初始化函数中调用下面的初始化网络的子函数 BOOL InitNetwork() file://初始化网络 { file://初始化TCP协议 BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData); if(ret != 0) { MessageBox("初始化套接字失败!"); return FALSE; } file://创建服务器端套接字 SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(serverSocket == INVALID_SOCKET) { MessageBox("创建套接字失败!"); closesocket(m_Socket); WSACleanup(); return FALSE; } file://绑定到本地一个端口上 sockaddr_in localaddr; = AF_INET; = htons(1688); = 0; if(bind(serverSocket ,(const struct sockaddr*)&localaddr, sizeof(sockaddr)) == SOCKET_ERROR) { MessageBox("绑定地址失败!"); closesocket(m_Socket); WSACleanup(); return FALSE; } file://注册网络异步事件,m_hWnd为应用程序的主对话框或主窗口的句柄 WSAAsyncSelect(serverSocket, m_hWnd, NETWORK_EVENT, FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE); listen(serverSocket, 5); file://设置侦听模式 return TRUE; } file://定义网络事件的响应函数 void OnNetEvent(WPARAM wParam, LPARAM lParam) { file://调用API函数,得到网络事件类型 int iEvent = WSAGETSELECTEVENT(lParam); file://得到发出此事件的客户端套接字 SOCKET pSock = (SOCKET)wParam;switch(iEvent) { case FD_ACCEPT: file://客户端连接请求 { OnAccept(); break; } case FD_CLOSE: file://客户端断开事件: { OnClose(pSock); break; } case FD_READ: file://网络数据包到达事件 { OnReceive(pSock); break; } case FD_WRITE: file://发送网络数据事件 { OnSend(pSock); break; } default: break; } } void OnAccept(SOCET pSock) file://响应客户端连接请求函数 { int len = sizeof(sockaddr); file://调用API函数,接受连接,并返回一个新套接字 file://还可以获得客户端的IP地址 SOCKET clientSocket = accept(serverSocket, (struct sockaddr*)&clientaddr, &len); file://为新的socket注册异步事件,注意没有Accept事件 if(WSAAsyncSelect(clientSocket ,m_hWnd, IP_EVENT, FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR) { MessageBox("注册异步事件失败!"); return; } file://自编函数,将此客户端的相关信息保存下来:套接字、 // IP地址、登陆时间 saveClientSocket(clientSocket,clientAddr,currentTimer); } void OnClose(SOCET pSock) { file://自编函数,结束与相应的客户端的通信,释放相应资源并做相应处理 endClientSocket(pSock); } void OnSend(SOCET pSock) { file://自编函数,在给客户端发数据时做一些预处理 handleOnSend(pSock); } void OnReceive(SOCET pSock) { recv(...); file://调用API函数,读出网络缓冲区中的数据包 file://自编函数,将此数据包和发出此数据的客户端 封装成一条网络消息 buildNetMsg(...); file://自编函数,将此网络消息放入一个消息队列中,由工作线程去处理 saveNetMsg(...); SetEvent(...); file://用事件对象触发工作线程} 客户端登陆后,随即把自己的计算机名发给服务器,服务器接到后,把它保存下来。这样服务器就可以显示所有在线客户端的信息了,包括:客户端计算机名、IP地址、登陆时间等。 注意: 客户端没有OnAccept()函数,但有OnConnect()函数。 工作线程 — 在你的应用程序初始化时,创建并启动一个工作线程 AfxBeginThread(WorkThread,this,THREAD_PRIORITY_NORMAL); 可能为应用程序的主对话框或主窗口的句柄 UINT WorkThread(LPVOID pParam) { while(1) { file://等待多重事件到来 int ret = WaitForMultipleObject(...); switch(ret) { case OBJECT_0: { if(bNewNetMsg) file://查看网络消息队列是否有新的网络消息 { readNetMsg(...); file://如有新的网络消息,则读出 handleNetMsg(...); file://处理此网络消息 } break; } case OBJECT_0 + 1: { file://做退出处理 break; } default: break; } return 0; } 客户端为单线程,登陆服务器时,用connect()函数给服务器发连接请求; 客户端没有OnAccept()函数,但有OnConnect()函数。 在OnConnect()函数里做发连接请求时的预处理; 在OnReceive()函数里响应并处理网络数据; 在OnClose()函数里响应服务器的关闭事件; 在OnSend()函数里做发数据时的预处理; 如果你还想实现各客户端之间的在线交流(即所谓的聊天室),你在客户端还可以基于UDP协议 再做一套多点对多点的局域网组播模型模型,以后在和你聊,你先把上面的程序实现。 以上的I/O异步模型基于Windows的消息机制,另外还可以用事件模型、重叠模型或完成端口模型, 建议你参考Windows网络编程指南之类的书。 如果你能对上面的机制很熟练,你肯定已经对Winsock编网络程序的机制有一定理解,接下来你可以进行更精彩的编程, 不仅可以在网上传输普通数据,而且还 以传输语音、视频数据,你还可以自己做一个聊天室,和你的同学在实验室的局域网里可以共同分享你的成果。

205 评论(11)

mm糖糖豆

建议报一个培训班,网络编程的前景很不错的,随着移动互联网的普及与发展,手机应用不断深入我们生活的方方面面,移动系统和软件应用的开发领域,成为了未来很具有潜力的行业之一。在未来5年内,合格软件人才的需求将远大于供给。其中,尤以JAVA、PHP、HTML5与CSS3开发、开发人才最为缺乏。

128 评论(13)

相关问答