基于TCP的半关闭

来源:互联网 发布:高压气瓶使用 知乎 编辑:程序博客网 时间:2024/05/18 00:58

windows的closesocket函数意味着完全断开连接(单方面断开连接)。完全断开不仅指无法传输数据,而且也不能接受数据。因此,在某些情况下closesocket函数断开连接就显得不太适用。

                             

为了解决这类问题,只关闭一部分数据交换中使用的流(half-close)的方法应运而生。断开一部分连接是指,可以传输数据但无法接收,或可以接收数据但无法传输。顾名思义就是只关闭流的一半。


套接字和流

两台主机通过套接字建立连接后进入可交换数据的状态,又称“流形成的状态”也就是把建立套接字后可交换数据的状态看作一种流。在套接字的流中,数据也只能向一个方向移动。

                      

一旦两台主机间建立了套接字连接,每个主机就会拥有单独的输入流和输出流。当然,其中一个主机的输入流与另一个主机的输出流相连,而输出流则与另一主机的输入流相连,半关闭只断开其中一个流,closesocket将同时断开两个流。

        

服务端

#include<iostream>#include<WinSock2.h>#pragma comment(lib,"ws2_32.lib")#define bufsize 1024using namespace std;void main() {WSADATA wsadata;SOCKET serverSocket,clientSocket;int szClientAddr,fpCnt;SOCKADDR_IN  serverAddr, clientAddr;char message[bufsize] = "\0";FILE *f;f = fopen("c:/1.txt", "rb" );if(WSAStartup(MAKEWORD(2, 2), &wsadata)!=0)cout<<"WSAStartup() error"<<endl;serverSocket = socket(PF_INET, SOCK_STREAM, 0);if(serverSocket == INVALID_SOCKET)cout<<"socket()  error"<<endl;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);serverAddr.sin_port = htons(9999);if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)cout << "bind () error" << endl;listen(serverSocket, 5);cout << "服务器启动成功!" << endl;szClientAddr = sizeof(clientAddr);clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddr, &szClientAddr);if (clientSocket == INVALID_SOCKET)  cout << "accept() error" << endl;else  cout << "已有客户端连接" << endl;while (1) {fpCnt = fread(message, 1, bufsize, f);if (fpCnt < bufsize) {send(clientSocket, message, fpCnt, 0);  //发送小于bufsize的数据break;}send(clientSocket, message, bufsize, 0);}shutdown(clientSocket, SD_SEND);recv(clientSocket, message, bufsize, 0);cout << "客户端消息" << message << endl;fclose(f);closesocket(clientSocket);closesocket(serverSocket);WSACleanup();getchar();}

客户端

#include<iostream>#include<WinSock2.h>#pragma comment(lib,"ws2_32.lib")#define bufsize 1024using namespace std;void main() {WSADATA wsadata;SOCKET clientSocket;SOCKADDR_IN  serverAddr;FILE *f;int  recvCnt;f = fopen("c:/2.txt", "wb");char message[bufsize] = "\0";if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)cout << "WSAStartup() error" << endl;if ((clientSocket = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)cout << "socket()  error" << endl;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");serverAddr.sin_port = htons(9999);if(connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr))==SOCKET_ERROR)cout<<"connect() error"<<endl;while ((recvCnt=recv(clientSocket,message,bufsize,0))!=0) {fwrite(message, 1, recvCnt, f);}cout << "接受数据完成!" << endl;send(clientSocket, "thank you!", 11, 0);fclose(f);closesocket(clientSocket);WSACleanup();}










0 0
原创粉丝点击