您的位置:首页 > 理论基础 > 计算机网络

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

2017-02-09 17:02 585 查看
网络通信
本节将基于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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息