基于MFC的socket编程
网络编程
1、windows 套接字编程(开放的网络编程接口)添加头文件#include<windows.h>
2、套接字及其分类
socket分为两种:(1)数据报socket:无连接套接字,可向指定的socket发送数据报消息,也可从指定的socket接收消息,提供双向的面向记录的数据流。但不能保证数据传输的顺序,也不能保证传输的可靠性。
(2)数据流socket:(例如电话呼叫),基于显式连接的套接字,通过没有记录的双向字节数据流,具有可靠的发送顺序,接收也是可靠的,适合处理大量数据的传输。
3、客户端/服务器模型(C/S模型)
网络编程常用的一种架构模型,将应用程序分为:
(1)前端客户端组件:运行在工作站上,负责从用户接收数据,为服务器处理数据,并形成到服务器的连接。
(2)后台服务器组件:等待客户端的连接,当服务器收到客户端的连接请求后,服务器会处理并返回客户端响应信息,客户端收到响应信息后,通过用户接口,呈现给用户.
目前很多项目都设计为分布式程序,以提高应用程序的性能。设计的关键是程序的性能和可扩展性。
4、网络字节顺序
标准的网络字节序是采用大端模式,而Intel采用小端模式。
若使用MFC 的socket编程,即服务器和客户端都使用MFC,则无需关心字节顺序。
5、使用WinSock API 进行编程
6、MFC对WinSock API 进行了封装。
提供了两个类:(1)类CAsynSocket一对一地封装了WinSock API。
(2)类CSocket提供以CArchive对象中序列化数据的Socket功能。
使用CSocket类,必须创建CSocket对象,使用对象底层的Socket句柄。
对客户端使用默认参数调用create()方法就好,对服务器socket对象,必须在create()方法中指定IP地址和端口。
下面是使用MFC socket编程的一个简单例子
服务器端程序:
(1)创建服务器
(2)连接请求连接的客户端
(3)与客户端进行数据传输(发送和接收)
(4)客户端断开服务器
界面如下图所示:
部分代码:
/*说明:本函数用于打开或关闭服务器,主要用到Create函数和Listen函数用于创建服务器和监听客户端。
其中端口号从编辑框获取,应用程序的可用端口范围是1024-65535。*/
void CPhoneServerDlg::OnBnClickedstartserver()
{
// TODO: 在此添加控件通知处理程序代码
if (m_connect)
{
delete listenSocket;
listenSocket = NULL;
m_connect = false;
SetDlgItemText(IDC_startserver, _T("打开服务器"));
UpdateEvent(_T("系统关闭服务器"));
return;
}
listenSocket = new CSerSocket();
listenSocket->m_pDlg = this; // 指定对话框为主对话框,不能少了这句 UpdateData(true);
if (!listenSocket->Create(m_port)) // 创建服务器的套接字,IP地址默认本机IP
{
AfxMessageBox(_T("创建套接字错误!"));
listenSocket->Close();
return;
}
if (!listenSocket->Listen())
{
AfxMessageBox(_T("监听失败!"));
listenSocket->Close();
return;
}
m_connect = true;
SetDlgItemText(IDC_startserver, _T("关闭服务器"));
UpdateEvent(_T("系统打开服务器"));
} /*说明:本函数在CServerSocket类中的OnAccept消息中调用,用于响应用户连接服务器的请求,主要函数为Accept,当连接成功后,
通过链表m_clientList保存新用户,更新日志,向新用户发送“Hello”表示欢迎。*/
void CPhoneServerDlg::AddClient()
{
CSerSocket *pSocket = new CSerSocket;
pSocket->m_pDlg = this;
listenSocket->Accept(*pSocket);
pSocket->AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE);
m_clientList.AddTail(pSocket);
m_usercount = m_clientList.GetCount();
UpdateEvent(_T("用户连接服务器"));
SendMSG(_T("hello"));
} /*本函数在CServerSocket类中的OnClose消息中调用,用到POSITION结构,
查找存储用户中哪位用户下线了,将下线用户释放,从链表中删除,并更新日志。*/
void CPhoneServerDlg::RemoveClient(CSerSocket *pSocket)
{
POSITION npos = m_clientList.GetHeadPosition();
POSITION nTmpPos = npos;
while (npos)
{
CSerSocket *pSocketItem = (CSerSocket *)m_clientList.GetNext(npos);
if (pSocketItem->m_hSocket == pSocket->m_hSocket)
{
pSocketItem->Close();
delete pSocketItem;
m_clientList.RemoveAt(nTmpPos);
m_usercount = m_clientList.GetCount();
UpdateData(false);
UpdateEvent(_T("用户离开"));
return;
}
nTmpPos = npos;
}
} /*说明:本函数在CServerSocket类中的OnReceive消息中调用,用于处理接收到的数据并控制电脑,
并将数据转发给所有用户(类似于群消息),通过CSocket类的GetPeerName函数可以获取用户的IP和端口号。*/
void CPhoneServerDlg::RecvData(CSerSocket *pSocket)
{
char *pData = NULL;
pData = new char[];
memset(pData, , sizeof(char) * );
UCHAR leng = ;
CString str;
if (pSocket->Receive(pData, , ) != SOCKET_ERROR)
{
str = pData;
ControlPC(str);
SendMSG(str);
}
delete pData;
pData = NULL;
} /*说明:本函数在所有需要更新日志的地方都有调用,方便服务器记录用户的登录和退出事件。*/
void CPhoneServerDlg::UpdateEvent(CString str)
{
CString string;
CTime time = CTime::GetCurrentTime();
// 获取系统当前时间
str += _T("\r\n");
// 用于换行显示日志
string = time.Format(_T("%Y/%m/%d %H:%M:%S ")) + str;
// 格式化当前时间
int lastLine = m_event.LineIndex(m_event.GetLineCount() - );
//获取编辑框最后一行索引
m_event.SetSel(lastLine + , lastLine + , );
//选择编辑框最后一行
m_event.ReplaceSel(string);
} /*说明:本函数在发送函数SendMSG中调用,用于字符集的转换,将宽字符转换为多字符集,不经转换的话,接收方只能接收一个字节。*/
BOOL CPhoneServerDlg::WChar2MByte(LPCWSTR srcBuff, LPSTR destBuff, int nlen)
{
int n = ;
n = WideCharToMultiByte(CP_OEMCP, , srcBuff, -, destBuff, , , FALSE);
if (n<nlen)return FALSE;
WideCharToMultiByte(CP_OEMCP, , srcBuff, -, destBuff, nlen, , FALSE);
return TRUE;
} /*说明:发送函数,用于发送消息给所有用户,主要函数为Send,在AddClient和RecvData中都有调用,可以随时调用发消息给用户。*/
void CPhoneServerDlg::SendMSG(CString str)
{
char *pSend = new char[str.GetLength()];
memset(pSend, , str.GetLength()*sizeof(char));
if (!WChar2MByte(str.GetBuffer(), pSend, str.GetLength()))
{
AfxMessageBox(_T("字符转换失败"));
delete pSend;
return;
}
POSITION nPos = m_clientList.GetHeadPosition();
while (nPos)
{
CSerSocket* pTemp = (CSerSocket*)m_clientList.GetNext(nPos);
pTemp->Send(pSend, str.GetLength());
}
delete pSend;
}
客户端界面如下:
部分代码:
void CPhoneClinetDlg::OnBnClickedconnect()
{
// TODO: 在此添加控件通知处理程序代码
if (m_connect) // 如果已经连接,则断开服务器
{
m_connect = false;
pSock->Close();
delete pSock;
pSock = NULL;
m_conpc.SetWindowTextW(_T("连接服务器"));
UpdateData(false);
return;
}
else // 未连接,则连接服务器
{
pSock = new CClientSocket();
if (!pSock->Create()) //创建套接字
{
AfxMessageBox(_T("创建套接字失败!"));
return;
}
}
if (!pSock->Connect(_T("127.0.0.1"), port)) //连接服务器
{
AfxMessageBox(_T("连接服务器失败!"));
return;
}
else
{
m_connect = true;
m_conpc.SetWindowTextW(_T("断开服务器"));
UpdateData(false);
}
}
void CPhoneClinetDlg::OnBnClickedsend()
{
// TODO: 在此添加控件通知处理程序代码
if (!m_connect)return; //未连接服务器则不执行
UpdateData(true); //获取界面数据
if (m_datasend != "")
{
char* pBuff = new char[m_datasend.GetLength() * 2];
memset(pBuff, 0, m_datasend.GetLength() * 2);
WChar2MByte(m_datasend.GetBuffer(0), pBuff, m_datasend.GetLength() * 2);
pSock->SendMSG(pBuff, m_datasend.GetLength() * 2);
}
}
基于MFC的socket编程的更多相关文章
- 基于MFC的socket编程(异步非阻塞通信)
对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清, ...
- 基于C#的socket编程的TCP同步实现
该博客源著地址https://www.cnblogs.com/sunev/archive/2012/08/05/2604189.html 一.摘要 总结一下基于C#的TCP传输协议的涉及到的常用方法及 ...
- 基于win32的socket编程及程序实现
初步研究了win32平台的Windows Sockets,它是Microsoft Windows的网络程序设计接口,它是从Berkeley Sockets扩展而来的,以动态链接库的形式提供给我们使用. ...
- Java网络编程学习A轮_07_基于Buffer的Socket编程
示例代码: https://github.com/gordonklg/study,socket module A. LineSeparate 基于 Buffer 实现逐行读取的 EchoServer ...
- 【转/TCP协议编程】 基于TCP的Socket 编程
基于TCP(面向连接)的socket编程,分为客户端和服务器端. 客户端的流程如下: (1)创建套接字(socket) (2)向服务器发出连接请求(connect) (3)和服务器端进行通信(send ...
- 基于java的socket编程
#开头的废话#学习java已经半个月了,原本在抠教材里面的字眼时,觉得教材好厚,要看完不知道要到猴年马月去了.突然在网上看到一个教程,里面老师说学编程语言书不用太细看,看个大概,知道里面讲些什么就好, ...
- Winfrom 基于TCP的Socket 编程
基于TCP的Socket基础例子 服务端的代码 public partial class Form1 : Form { public Form1() { InitializeComponent(); ...
- Java基于TCP的Socket编程练习
环境:Notpad ++ 6.0 + JDK 6.0.31 问题:使用套接字编写客户-服务器程序,实现客户-服务器交互计算.客户将三角形3个边的长度发给服务器,服务器把计算出的三角形的面积返回给客户. ...
- 网络编程学习笔记(二)基于TCP的Socket编程
1.Socket:英文意思插座.两个Java应用程序可以通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket. 2.Socket通常用来实现client-server(客户端 ...
随机推荐
- PhoenixFD插件流体模拟——UI布局【Export】详解
Liquid Export 流体导出 本文主要讲解Export折叠栏中的内容.原文地址:https://docs.chaosgroup.com/display/PHX3MAX/Liquid+Expor ...
- python--第十六天总结(bootstrap)
一. 实现原理 网格布局是通过容器的大小,平均分为12份(可以修改),再调整内外边距,和表格布局有点类似但是也存在区别. 实现步骤如下: (1) 数据行.row 必须包含在容器.container 中 ...
- mysql链接服务器,update报错
select * from Openquery(MySQL, 'SELECT * FROM official.sys_hospital') 执行更新语句: ; 报错,错误信息: 链接服务器" ...
- Uncaught TypeError: form.attr is not a function 解决办法
前端form表单提交时遇到个问题,一直报错如下 首先说结论:form是个js对象,不是jQuery对象,不能用jquery对象的方法. 代码是: $(document).ready(function( ...
- Ubuntu开机时提示“piix4_smbus 0000:00:07.3: SMBus Host controller not enabled”
问题描述:Ubuntu开机时提示“piix4_smbus 0000:00:07.3: SMBus Host controller not enabled” 版本:Ubuntu 18.04 VMw ...
- 2019-04(1)(Python学习)
9.1 迭代器 创建迭代器的3种方法: 方法一: 容器对象添加 __iter__() 和 __next__() 方法(Python 2.7 中是 next()):__iter__() 返回迭代器对象本 ...
- 连接HTTP服务器
一.前提 Android 系统上面默认所有Http的请求都被阻止了. 需要在androidmanifest.xml的 application标签上加入 android:usesCleartextTra ...
- Microsoft SQL Server 错误:948
版本655指的是SQL2008, 版本611指的是SQL2005, (还有一个版本539指的是SQL2000) 楼主的情况属于典型的从高版本降低至低版本使用的情景. 按微软的官方说法, 是不支持从高版 ...
- Atomikos和GTS-Fescar和TCC-Transaction和TX-LCN分布式事物的比较
什么是分布式事物 分布式系统中保证不同节点之间的数据一致性的事物,叫做分布式事物. 为什么要用分布式事物 微服务,SOA等服务架构模式,一个是service产生多个节点,另一个是resource产生多 ...
- php 守护进程(Daemon)
守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务. 很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭. 守护进程一直在后台运行,脱离终端运行的程序 独立运行的守护进 ...