基于socket的网络通信实现(MFC)

								网络通信
	本节将基于socket编写服务器端和客户端,实现网络通信。程序采用MFC对话框框架,在visual stdio2012平台上实现。
	程序采用面向对象的方法设计,服务器端由CServerDlg构建,客户端由CClientDlg类构建。构建思路如下
	服务器端:
		(一)开启服务器
			1.加载套接字库
			2.创建套接字
			3.获取服务器端所在的IP地址
			4.绑定套接字和端口号
			5.监听来自客户端的消息
			6.设置异步套接字
		(二)响应客户端连接与接收信息
			当客户端与服务器端建立连接时,服务器端会接收到FD_ACCEPT的事件通知,构建FD_ACCEPT的事件内容
			当连接已经建立,服务器可以通过FD_READ事件来接受来自客户端的信息
		 (三) 发送信息
			用户在发送信息的文本框汇中编辑信息,然后单击发送按钮发送信息
服务器端界面如下:


实现代码如下:

void CServerDlg::OnBnClickedStartrun()
{
	// TODO: 在此添加控件通知处理程序代码
	//加载套接字库
	WORD version = MAKEWORD(2,0);
	WSADATA wsadata;
	if(WSAStartup(version, &wsadata)){
		MessageBox("加载Winsock dll 失败");
		return;
	}

	//创建套接字
	socket_server = socket(AF_INET, SOCK_STREAM, NULL);
	if(INVALID_SOCKET == socket_server){
		MessageBox("套接字创建失败!");
		return;
	}

	//获取主机名
	char hostname[20]  = "";
	if(gethostname(hostname, 20)){
		MessageBox("主机名获取失败");
		return;
	}

	//通过主机名来获取记录主机IP的结构
	hostent *htent = gethostbyname(hostname);
	if(htent == NULL){
		MessageBox("主机IP获取失败!");
		return;
	}

	//获取IP地址
	LPSTR lpAddr = htent->h_addr_list[0];
	IN_ADDR inAddr;
	memmove(&inAddr, lpAddr,4);
	CString ipAddress = inet_ntoa(inAddr);

	//绑定套接字
	SOCKADDR_IN addr;
	memset(&addr, 0, sizeof(SOCKADDR_IN));   //将地址内容清零
	addr.sin_family = AF_INET;
	addr.sin_port = htons(80);
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	if( bind(socket_server, (sockaddr*)&addr,sizeof(sockaddr)) ){
		MessageBox("绑定IP和PORT出错");
		return;
	}

	//监听
	if(listen(socket_server,SOMAXCONN)){
		MessageBox("异步设置出错");
		return;
	}

	//设置异步套接字
	if( WSAAsyncSelect( socket_server, this->m_hWnd, WM_SOCKET, FD_ACCEPT| FD_READ) ){
		MessageBox("异步设置出错");
		return;
	}

	m_recv += "服务器端已开启,等待客户端连接\r\n";
	UpdateData(false);
}

//添加异步处理消息响应函数
LRESULT  CServerDlg::OnSocket(WPARAM wParam, LPARAM lParam){
	switch(lParam){
		case FD_ACCEPT:{
			SOCKADDR_IN addr;
			int len = sizeof(SOCKADDR_IN);
			socket_client = accept(socket_server, (sockaddr*)&addr, &len);
			if(socket_client == INVALID_SOCKET){
				MessageBox("客户端套接字创建出错");
				return NULL;
			}
			//获取对方的IP
			m_status += "客户端IP:  ";
			m_status += inet_ntoa(addr.sin_addr);
			UpdateData(false);   //用来显示客户端的IP地址
			break;
		 }

		case FD_READ:{
			UpdateData(true);
			char buff[1024] = "";
			if(!recv(socket_client, buff,1024,NULL)){
				MessageBox("数据接收出错");
				return NULL;
			}
			m_recv += "\r\n 客户端: ";
			m_recv += buff;
			UpdateData(false);
			break;
			}
	}
	return NULL;
}

void CServerDlg::OnBnClickedSendbtn()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(true);
	if(SOCKET_ERROR == send(socket_client, m_send.GetBuffer(1), m_send.GetLength(), NULL)) {
		MessageBox("消息发送出错");
		return;
	}
	m_recv += "\r\n服务器端: ";
	m_recv += m_send;
	m_send = "";
	UpdateData(false);
}


void CServerDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码

	if(WSACleanup()) {
		MessageBox("卸载Winsock dll 失败!");
		return;
	}
	if(socket_server){
		closesocket(socket_server);
	}
	if(socket_client){
		closesocket(socket_client);
	}
	CDialog::OnCancel();
}
客户端的编写思路与服务器端类似,具体如下:
	客户端:
		(一)连接服务器
			1.加载Winsock dll
			2.准备套接字
			3.连接服务器
			4.设置异步套接字
		(二)响应读取
		(三)发送信息

void CClientDlg::OnBnClickedConnect()
{
	// TODO: 在此添加控件通知处理程序代码

	//加载WinSock dll
	WORD version = MAKEWORD(2,0);
	WSADATA wsadata;
	if( WSAStartup( version, &wsadata) ){
		MessageBox("加载WinSock失败!");
		return;
	}

	//创建套接字
	socket_client = socket(AF_INET, SOCK_STREAM, NULL);
	if(INVALID_SOCKET == socket_client){
		MessageBox("创建套接字失败!");
		return;
	}

	//绑定通信地址
	UpdateData(true);
	SOCKADDR_IN addr;
	memset(&addr, 0, sizeof(SOCKADDR_IN));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(80);
	addr.sin_addr.S_un.S_addr = inet_addr(m_ip);
	if(connect(socket_client, (sockaddr*)&addr, sizeof(sockaddr))){
		MessageBox("尝试与服务器的连接失败!");
		return;
	}

	//设置异步套接字
	if( WSAAsyncSelect(socket_client, this->m_hWnd, WM_SOCKET, FD_READ)){
		MessageBox("异步设置失败!");
		return;
	}
	m_recv += "连接服务器成功!\r\n";
	UpdateData(false);

}

LRESULT CClientDlg::OnSocket(WPARAM wParam , LPARAM lParam){
	switch (lParam){
		case FD_READ:{
			UpdateData(true);
			char buff[1024] = "";
			if(!recv(socket_client, buff , 1024, NULL)){
				MessageBox("数据接收出错");
				return NULL;
			}
			m_recv += "\r\n 服务器端: ";
			m_recv += buff;
			UpdateData(false);
		}
		
	}
	return NULL;
}

void CClientDlg::OnBnClickedSendbtn()
{
	// TODO: 在此添加控件通知处理程序代码

	UpdateData(true);
	if( SOCKET_ERROR == send(socket_client, m_send.GetBuffer(1), m_send.GetLength(),NULL)){
		MessageBox("消息发送出错");
		return;
	}
	m_recv += "\r\n 客户端: ";
	m_recv += m_send;
	m_send = "";
	UpdateData(false);
}


void CClientDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	if(WSACleanup()){
		MessageBox("卸载Winsock dll失败!");
		return;
	}
	if(socket_client){
		closesocket(socket_client);
	}
	CDialog::OnCancel();
}


猜你喜欢

转载自blog.csdn.net/qq_17152131/article/details/54949136