MFC之Socket服务端编程

       这些天由于工作需要,需要用到MFC的Socket编程,于是和这个许久未见的老朋友C++又有了接触,虽然彼此有些生疏,但还算顺利,哈哈。。。。,经过百度谷歌一番,着实发现资料很多,但是有些会将我们带入误区,特别如果你是个初学者。所以就自己这次的经验总结下吧,闲着也是闲着。

       一、假如你是个初学者,那就让我们先了解了解Socket的一些基本知识

       1、什么是TCP/IP、UDP?

       TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。

  UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。

       2 、TCP/IP、UDP之间的区别

       A、TCP是面向连接的传输控制协议,而UDP提供了无连接的数据报服务;
       B、TCP具有高可靠性,确保传输数据的正确性,不出现丢失或乱序;UDP在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作;
       C、也正因为以上特征,UDP具有较好的实时性,工作效率较TCP协议高;
       D、UDP段结构比TCP的段结构简单,因此网络开销也小。

       3、Socket是什么?

       Socket熟称“套接字”,是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面(Facade)模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。     

       4、Socket编程有哪些类型?

       常用的Socket类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。这里主要讲下SOCK_STREAM和SOCK_DGRAM,其中SOCK_STREAM是基于TCP/IP协议传输的,SOCK_DGRAM就是基于UDP的,两张协议不可相互通信,所以在创建Socket的时候要注意,服务端和客户端要采用同一种协议。

       二、Socket服务端,启动Socket和监听客户端的连接

BOOL CPostClientDlg::InitSocket()
{
	//m_socket=socket(AF_INET,SOCK_DGRAM,0); //基于udp
	m_socket=socket(AF_INET,SOCK_STREAM,0);//基于tcp
	
	if(INVALID_SOCKET==m_socket)
	{
		MessageBox("套接字创建失败!");
		return FALSE;
	}
	SOCKADDR_IN addrSock;
	addrSock.sin_family=AF_INET;
	addrSock.sin_port=htons(6000);
	addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

	int retval;
	retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
	
	if(SOCKET_ERROR==retval)
	{
		closesocket(m_socket);
		MessageBox("绑定失败!");
		return FALSE;
	}

	//创建一线程监听
	RECVPARAM *pRecvParam=new RECVPARAM;
	pRecvParam->sock=m_socket;
	pRecvParam->hwnd=m_hWnd;
	HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
	CloseHandle(hThread);
	
	return TRUE;
}

 

DWORD WINAPI CPostClientDlg::RecvProc(LPVOID lpParameter)
{
	SOCKET sock=((RECVPARAM*)lpParameter)->sock;
	HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
	delete lpParameter;	//释放内存的操作
	
	if(listen(sock,5) == SOCKET_ERROR)
    	{
    	    //监听客户端,如果是基于UDP的,则不需要listen
	    return 0;
    	} 

	SOCKADDR_IN addrFrom;
	int len=sizeof(SOCKADDR);

	char recvBuf[200]={0};//获取客户端发送的消息
	int retval;
	while(TRUE)
	{
		SOCKET ConnectSocket = accept(sock,(sockaddr*)&addrFrom,&len); //得到客户端的IP地址。 
		retval=recv(ConnectSocket,recvBuf,200,0); 
		if(SOCKET_ERROR==retval)
			break;

	}
	return 0;
}

 其中结构体RECVPARAM定义如下:

struct RECVPARAM
{
 SOCKET sock;
 HWND hwnd;
};

 

 就这么简单,服务端就ok了。

 之前在网上看到的大部门创建服务端的Socket的基本上都是在主线程里加监听,犹如

BOOL CPostClientDlg::InitSocket()
{
	//m_socket=socket(AF_INET,SOCK_DGRAM,0); //基于udp
	m_socket=socket(AF_INET,SOCK_STREAM,0);//基于tcp
	
	if(INVALID_SOCKET==m_socket)
	{
		MessageBox("套接字创建失败!");
		return FALSE;
	}
	SOCKADDR_IN addrSock;
	addrSock.sin_family=AF_INET;
	addrSock.sin_port=htons(6000);
	addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

	int retval;
	retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
	
	if(SOCKET_ERROR==retval)
	{
		closesocket(m_socket);
		MessageBox("绑定失败!");
		return FALSE;
	}

	//监听
	if(listen(m_socket,5) == SOCKET_ERROR)
    	{
    	    //监听客户端,如果是基于UDP的,则不需要listen
	    return FALSE;
    	} 
	while(TRUE)
	{
		SOCKET ConnectSocket = accept(m_socket,(sockaddr*)&addrFrom,&len); //得到客户端的IP地址。 
		.....

	}
	
	return TRUE;
}

 

这样会导致主线程得不到释放程序会假死现象。

当然这是比较原始的Socket编程了,现在对Socket封装的类也有很多,编程起来也很方便,比如用的比较多的是CAsyncSocket,CSocket等等,但是如果要学习的话还是原始的好,毕竟被包装过的,看不到他的真面目,哈哈!

       服务端创建Socket就这么简单,希望对你有所帮助!

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
环境:Windows XP SP3、 VC++ 6.0、 Windows 2003 SDK 使用步骤: 1、下载解压之后,使用VC++ 6.0打开两个工程:一个是SocketServer和一个ClientSocket工程。 2、首先运行服务器端工程,选默认的端口1008 3、然后运行客户端工程,选默认的端口1008和默认的服务器地址 4、再运行多个客户端进程 5、如果一切正常,可以每个客户端的消息发送,我们可以在服务端和各个客户端同步看到消息 实现一个服务器对多个客户端的关键是,在服务端的使用集合CPtrList类用保存客户端的socket对象,思想与Java中的编程思想一样,只不过Java中会使用多线程技术,在Vector集合保存客户端的socket对象,而MFC框架提供了CSocket类,它是一个异步通信的类,所以看上去代码比较Java的多线程代码简单的实现了一个对多的即时通讯功能。另外,MFC提供了CSocketFile类和CArchive类与CSocket类实现了C++的网络通讯编程功能。 本示例注释非常详细,所有的辅助类都放一个util目录中,然后在工程中分了一个目录来管理这些辅助类,使用代码非常清晰。手动书写部分的代码是按Java的规范书写,当然其它代码由IDE生成的,所以是MS的风格,所以当你看代码时,只要是使用“骆驮命名法”的方法都是本人书写的功能性代码。 参看的思路:在服务端要从回调方法onAccept读起;而客户端代码主要从OnSendButton方法读起,即可理解整个代码的意思。 阅读对象:具有Java的Socket编程经验的人员,并且希望能够书写出比Java效率更高的即时通讯程序的人员
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值