网络通信之TCP

  1. TCP通信过程
    在这里插入图片描述

2. 服务器端

  • 建立连接阶段

(1)调用socket(),分配文件描述符,即监听套接字
(2)调用bind(),将套接字与本地IP地址和端口绑定
(3)调用listen(),监听特定端口,socket()创建的套接字是主动的,
(4)调用listen使得该文件描述符为监听套接字,变主动为被动
(5)调用accept(),阻塞等待客户端连接

  • 数据交互阶段

(1)调用read(),阻塞等待客户端发送的请求,收到请求后从read()返回,处理客户端请求
(2)调用write(),将处理结果发送给客户端,然后继续调用read()等待客户端请求

  • 关闭阶段

(1)当read()返回0的时候,说明客户端发来了FIN数据包,即关闭连接,也会调用close()关闭连接套接字和监听套接字
通过自定义消息响应函数创建服务器端(mfc实现)

//加载套接字库
	WORD wVersionRequested;		//指定加载winsock版本高字节为副版本,低字节为主版本
	WSAData wsaData;
	int Error;
	wVersionRequested=MAKEWORD(1,1);	//第一个为高字节,第二个为低字节
	Error=WSAStartup(wVersionRequested,&wsaData);	//加载套接字库
	if (Error!=0)
	{
		return FALSE;
	}
	if (LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)
	{
		MessageBox("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
		return FALSE;
	}
	//创建,绑定,收听
	SOCKET sockServer;
	sockServer=socket(AF_INET,SOCK_STREAM,0);
	SOCKADDR_IN addrServer;
	addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	addrServer.sin_family=AF_INET;
	addrServer.sin_port=htons(8888);
	bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
	listen(sockServer,5);
	//自定义accept和receive消息函数
	#define WM_SOCKET WM_USER+101
	ON_MESSAGE(WM_SOCKET,&OnSocketMessage)
	afx_msg LRESULT OnSocketMessage(WPARAM wParam,LPARAM lParam);	//自定义TCP消息
	int i= WSAAsyncSelect(sockServer,this->m_hWnd,WM_SOCKET,FD_ACCEPT|FD_READ);
	LRESULT CIOMatchingDlg::OnSocketMessage(WPARAM wParam,LPARAM lParam)
	{
		switch(lParam)
		{
			case FD_ACCEPT:
			{
				sockClient=accept(sockServer,NULL,NULL);
				m_listPutData.AddString("绑定成功");
			}
			break;   
			case FD_READ:
			{
				CString strReceiveData,strSendData;
				//接受数据
				char chReceiveData[100];
				int nLen=recv(sockClient,chReceiveData,sizeof(chReceiveData)-1,0);
				chReceiveData[nLen]=0;
				strReceiveData=chReceiveData;
				//发送数据
				strSendData="接受指令成功";
				send(sockClient,strSendData,strSendData.GetLength(),0);
			}
			break;
		return 0;
	}
	

2. 客户端

  • 建立连接阶段

(1)调用socket(),分配文件描述符
(2)调用connect(),向服务器发送建立连接请求

  • 数据交互阶段

(1)调用write(),将请求发送给服务器
(2)调用read(),阻塞等待服务器应答

  • 关闭连接

(1)当没有数据发送的时候,调用close()关闭连接套接字,即关闭连接,向服务器发送FIN数据报
通过自定义消息响应函数创建客户区端(mfc实现)

//加载套接字库
	WORD wVersionRequested;
	WSADATA wsaData;
	int Error;
	wVersionRequested=MAKEWORD(1,1);
	Error=WSAStartup(wVersionRequested,&wsaData);
	if (err!=0)
	{
		return FALSE;
	}
	if (LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)
	{
		MessageBox("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
		return FALSE;
	}
	//创建,连接
	SOCKET sockClient;
	sockClient=socket(AF_INET,SOCK_STREAM,0);
	SOCKADDR_IN addrClient;
	addrClient.sin_addr.S_un.S_addr=inet_addr("192.168.0.105");
	addrClient.sin_family=AF_INET;
	addrClient.sin_port=htons(8888);
	connect(sockClient,(SOCKADDR*)&addrClient,sizeof(SOCKADDR));
	//发送数据
	CString strSendData,strReceiveData;
	GetDlgItemText(IDC_SENDDATA_EDIT,strSendData);
	send(sockClient,strSendData.GetBuffer(1),strSendData.GetLength(),0);
	//自定义receive消息
	#define WM_SOCKET WM_USER+101
	ON_MESSAGE(WM_SOCKET,&OnSocketMessage)
	afx_msg LRESULT OnSocketMessage(WPARAM wParam,LPARAM lParam);	//自定义TCP消息
	int i= WSAAsyncSelect(sockServer,this->m_hWnd,WM_SOCKET,FD_READ);
	LRESULT CIOMatchingDlg::OnSocketMessage(WPARAM wParam,LPARAM lParam)
	{
		//接受数据
		CString strReceiveData;
		char chReceiveData[100];
		int nLen=recv(sockClient,chReceiveData,sizeof(chReceiveData)-1,0);
		chReceiveData[nLen]=0;
		strReceiveData=chReceiveData;	 
		return 0;
	 }

猜你喜欢

转载自blog.csdn.net/qq_29187197/article/details/82891160