一个简单的UDPServer实现

源代码在线查看: 一个简单的udp server实现.txt

软件大小: 4 K
上传用户: dsdsads
关键词: UDPServer
下载地址: 免注册下载 普通下载 VIP

相关代码

				一个简单的UDP Server实现
				
				作者:武乃辉
				
				
				
				一、思路
				1、建立接收socket,将socket和指定的端口绑定
				2、创建接收线程,在线程中调用ioctlsocket()判断是否接收到数据,接收到数据时调用OnReceive()(类似CSocket中的OnReceive())
				3、在OnReceive中申请空间调用recvfrom接收数据
				4、建立发送socket,和INADDR_ANY绑定
				5、调用sendto发送数据
				二、本代码直接使用socket API实现UDP通讯 
				相关的函数有:
				WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);//初始化socket库
				WSACleanup();//释放socket库
				socket(int af,int type,int protocol); //建立socket
				setsockopt(SOCKET s,int level,int optname,const char FAR * optval,int optlen);//设置socket或者协议的属性
				bind(SOCKET s,const struct sockaddr FAR * name,int namelen);//地址和socket绑定
				sendto(SOCKET s,const char FAR * buf,int len,int flags,const struct sockaddr FAR * to,int tolen);//发送消息
				ioctlsocket(SOCKET s,long cmd,u_long FAR * argp);//获取socket状态,可以获取socket缓冲中数据长度,利用这个函数可以实现类似CSocket中的OnReceive()函数(在接收数据之前调用)
				recvfrom(SOCKET s,char FAR * buf,int len,int flags,struct sockaddr FAR * from,int FAR * fromlen);//接收数据
				
				三、代码说明
				1、UDPServer.h和UDPServer.cpp是实现类CUDPServer的头文件和实现文件,udpdemo.cpp是演示程序
				2、编译环境在win2000 vc6.0下编译通过
				3、编译时需要在vc的project的setting中连接Ws2_32.lib库
				
				
				// UDPServer.h: interface for the CUDPServer class.
				//
				//////////////////////////////////////////////////////////////////////
				#if !defined(UDPSERVER_H_INCLUDED_)
				#define UDPSERVER_H_INCLUDED_
				
				#if _MSC_VER > 1000
				#pragma once
				#endif // _MSC_VER > 1000
				
				#include    // Ws2_32.lib
				#define CLOSE_SOCKET(X) if(X!=INVALID_SOCKET){closesocket(X);X=INVALID_SOCKET;}
				class CUDPServer  
				{
				private:
					char m_szLocalIP[20];
					char m_szHostName[30];
					int  m_RecvPort;
					char m_szRemoteIP[20];
					int  m_RemotePort;
					HANDLE m_RecvThread;
					DWORD  m_ThreadID;
				private:
					void InitMemberVariable();
				public:
					SOCKET m_SckRecive;
					SOCKET m_SckSend;
					bool m_bReciveFlag;
					CUDPServer();
					virtual ~CUDPServer();
					void Initialize();
					void Destory();
					//初始化socket lib
					bool InitSocketLib(WORD wVersion=0x0202);
					void CleanSocketLib();
					//创建发送socket
					bool CreateSendSocket();
					//创建接收socket
					bool CreateRecvSocket(int RecvPort=9527);
					//发送
					int SendMsg(char * szBuf,int length,char * szremoteIP=NULL,int port=0);
					//启动接收线程
					bool StartRecv();
					//停止接收线程
					bool StopRecv();
					//接收线程函数,
					static DWORD WINAPI ReceiveThread(LPVOID lpParameter);   // 线程函数
				
					//当有数据时,调用OnReceive,length表示数据长度
					void OnReceive(long length);
					static DWORD WINAPI OnReceiveThread(LPVOID lpParameter);   // 线程函数
				};
				
				#endif // !defined(UDPSERVER_H_INCLUDED_)
				
				// UDPServer.cpp: implementation of the CUDPServer class.
				//
				//////////////////////////////////////////////////////////////////////
				
				#include "UDPServer.h"
				#include 
				//////////////////////////////////////////////////////////////////////
				// Construction/Destruction
				//////////////////////////////////////////////////////////////////////
				//********************************************************************
				CUDPServer::CUDPServer()
				{
					Initialize();
				}
				//********************************************************************
				CUDPServer::~CUDPServer()
				{
					Destory();
				}
				//********************************************************************
				void CUDPServer::Initialize()
				{
					InitSocketLib(0x0202);
					InitMemberVariable();
				}
				//********************************************************************
				void CUDPServer::Destory()
				{
					if(m_bReciveFlag)
					{
						StopRecv();
					}
					CleanSocketLib();
				}
				//********************************************************************
				void CUDPServer::InitMemberVariable()
				{
					memset(m_szLocalIP,0,20);
					strcpy(m_szLocalIP,"127.0.0.1");
					memset(m_szHostName,0,30);
					m_RecvPort = 9527;
					m_SckRecive = INVALID_SOCKET;
					m_SckSend = INVALID_SOCKET;
					memset(m_szRemoteIP,0,20);
					strcpy(m_szRemoteIP,"127.0.0.1");
					m_RemotePort = 9527;
					m_RecvThread = NULL;
					m_ThreadID = 0;
					m_bReciveFlag = false;
				}
				//********************************************************************
				bool CUDPServer::InitSocketLib(WORD wVersion)
				{
					WSADATA wsd;
					int ret = WSAStartup(wVersion,&wsd);
					if(ret!=0)
					{
						WSACleanup();
						return false;
					}
					return true;
				}
				//********************************************************************
				void CUDPServer::CleanSocketLib()
				{
					WSACleanup();
				}
				//********************************************************************
				//创建发送socket
				bool CUDPServer::CreateSendSocket()
				{
					int ret;
					bool flag;
					SOCKADDR_IN addr;
				
					CLOSE_SOCKET(m_SckSend);
					m_SckSend = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP); 
					if(m_SckSend==INVALID_SOCKET)
					{
						return false;
					}
					flag = true;
					//设置允许地址复用
					ret = setsockopt(m_SckSend,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag));
					if(ret!=0)
					{
						CLOSE_SOCKET(m_SckSend);
						return false;
					}
					//绑定
					ZeroMemory(&addr,sizeof(addr));
					addr.sin_family = AF_INET;
					addr.sin_addr.s_addr = INADDR_ANY;
					//addr.sin_port = htons(m_RecvPort);
					//addr.sin_port = m_RecvPort;
					ret = bind(m_SckSend,(struct sockaddr *)&addr,sizeof(addr));
					if(ret!=0)
					{
						CLOSE_SOCKET(m_SckSend);
						return false;
					}
					return true;
				}
				//********************************************************************
				//创建接收socket
				bool CUDPServer::CreateRecvSocket(int RecvPort)
				{
					int ret;
					bool flag;
					SOCKADDR_IN addr;
				
					CLOSE_SOCKET(m_SckRecive);
					m_RecvPort = RecvPort;
					//创建socket
					m_SckRecive = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP); 
					if(m_SckRecive==INVALID_SOCKET)
					{
						return false;
					}
					flag = true;
					//设置允许地址复用
					ret = setsockopt(m_SckRecive,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag));
					if(ret!=0)
					{
						CLOSE_SOCKET(m_SckRecive);
						return false;
					}
					/*const int routenum = 10;
					ret = setsockopt(m_SckMultiCastSend,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&routenum,sizeof(routenum));
					if(ret!=0)
					{
						CLOSE_SOCKET(m_SckMultiCastSend);
						return false;
					}
					const int loopback = 1; //禁止回馈
					ret = setsockopt(m_SckMultiCastSend,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&loopback,sizeof(loopback));
					if(ret!=0)
					{
						CLOSE_SOCKET(m_SckMultiCastSend);
						return false;
					}
					flag=true;
					//设置该套接字为广播类型,
					setsockopt(m_SckMultiCastSend,SOL_SOCKET,SO_BROADCAST,(char FAR *)&flag,sizeof(flag));*/
				
					//绑定
					ZeroMemory(&addr,sizeof(addr));
					addr.sin_family = AF_INET;
					addr.sin_addr.s_addr = INADDR_ANY;
					addr.sin_port = htons(m_RecvPort);
					//addr.sin_port = m_MultiCastPort;
					ret = bind(m_SckRecive,(struct sockaddr *)&addr,sizeof(addr));
					if(ret!=0)
					{
						CLOSE_SOCKET(m_SckRecive);
						return false;
					}
					return true;
				}
				//********************************************************************
				//发送
				int CUDPServer::SendMsg(char * szBuf,int length,char * szremoteIP,int port)
				{
					int ret;
					SOCKADDR_IN addr;
					if(m_SckSend==INVALID_SOCKET)
					{
						return -1;
					}
					if(szremoteIP!=NULL)
					{
						strcpy(m_szRemoteIP,szremoteIP);
						m_RemotePort = port;
					}
					ZeroMemory(&addr,sizeof(addr));
					addr.sin_family = AF_INET;
					addr.sin_addr.s_addr = inet_addr(m_szRemoteIP);
					addr.sin_port = htons(m_RemotePort);
					ret = sendto(m_SckSend,szBuf,length,0,(sockaddr *)&addr,sizeof(addr));	
					if(ret == SOCKET_ERROR)
					{
						return -1;
					}
					return ret;	
				}
				//********************************************************************
				//启动接收线程
				bool CUDPServer::StartRecv()
				{
					if(m_SckRecive==INVALID_SOCKET)
					{
						if(!CreateRecvSocket())
						{
							return false;
						}
					}
					if(m_bReciveFlag)
					{
						return true;
					}
					//m_RecvThread = CreateThread(NULL,0,ReceiveThread,this,0,&m_ThreadID);
					m_RecvThread = CreateThread(NULL,0,OnReceiveThread,this,0,&m_ThreadID);
					
					if(m_RecvThread==NULL)
					{
						return false;
					}
					return true;
				}
				//********************************************************************
				//停止接收线程
				bool CUDPServer::StopRecv()
				{
					if(!m_bReciveFlag)
					{
						return true;
					}
					CLOSE_SOCKET(m_SckRecive);
					if(m_RecvThread!=NULL)
					{
						WaitForSingleObject(m_RecvThread,INFINITE);
						m_RecvThread = NULL;
						m_ThreadID = 0;
					}
					return true;
				}
				//********************************************************************
				//接收线程函数,
				DWORD WINAPI CUDPServer::ReceiveThread(LPVOID lpParameter)
				{
					int addr_len;
					struct sockaddr_in addr;
					char szRecBuf[10000];
					int iRecLen;
					CUDPServer * pUDPServer;
					pUDPServer = (CUDPServer *)lpParameter;
					pUDPServer->m_bReciveFlag = true;
					printf("Receive Thread Started.\n");
					/*addr.sin_family = AF_INET;
					addr.sin_addr.s_addr = INADDR_ANY;
					addr.sin_port = htons(pNetMultiCast->m_MultiCastPort);*/
					while(pUDPServer->m_bReciveFlag)
					{
						 
						addr_len = sizeof(addr);
						iRecLen = recvfrom(pUDPServer->m_SckRecive,szRecBuf,10000,0,(struct sockaddr *)&addr,&addr_len);
						if(iRecLen==SOCKET_ERROR||iRecLen						{
							pUDPServer->m_bReciveFlag = false;
						}
						else
						{
							szRecBuf[iRecLen] = 0;
							printf("Receive from %s :%s\n",inet_ntoa(addr.sin_addr),szRecBuf);
						}
					}
					printf("Receive Thread Ended.\n");
					return 0;
				}
				
				//********************************************************************
				void CUDPServer::OnReceive(long length)
				{
					//length 是socket列队中的第一个报文长度
					//在本函数中可以进行业务的处理
					char *pbuf;
					int addr_len,iRecLen;;
					struct sockaddr_in addr;
					pbuf = new char[length+1];
					memset(pbuf,0,length+1);
					addr_len = sizeof(addr);
					iRecLen = recvfrom(m_SckRecive,pbuf,length,0,(struct sockaddr *)&addr,&addr_len);
					if(iRecLen==SOCKET_ERROR||iRecLen					{
						printf("Receive Failed!");
					}
					else
					{
						pbuf[length] = 0;
						printf("Receive from %s :%s\n",inet_ntoa(addr.sin_addr),pbuf);
					}
					delete [] pbuf;
					pbuf = NULL;
				}
				//********************************************************************
				DWORD WINAPI CUDPServer::OnReceiveThread(LPVOID lpParameter)
				{
					int ret;
					unsigned long lLength;
					CUDPServer * pUDPServer;
					pUDPServer = (CUDPServer *)lpParameter;
					pUDPServer->m_bReciveFlag = true;
					printf("Receive Thread Started.\n");
					while(pUDPServer->m_bReciveFlag)
					{
						ret = ioctlsocket(pUDPServer->m_SckRecive,FIONREAD,&lLength);
						if(ret!=0)
						{
							pUDPServer->m_bReciveFlag = false;
						}
						else
						{
							if(lLength>0)
							{
								pUDPServer->OnReceive(lLength);
							}
						}
					}
					printf("Receive Thread Ended.\n");
					return 0;
				}
				
				//udpdemo.cpp
				#include 
				#include "UDPServer.h"
				
				
				
				using namespace std;
				
				int main(int argc,char *argv)
				{
					char szBuf[100];
					CUDPServer pUDPServer;
					cout					pUDPServer.CreateRecvSocket(9000);
					pUDPServer.CreateSendSocket();
					pUDPServer.StartRecv();
					while(1)
					{
						memset(szBuf,0,100);
						cout						cin>>szBuf;
						if(strcmp(szBuf,"quit")==0)
						{
							pUDPServer.StopRecv();
							break;
						}
						pUDPServer.SendMsg(szBuf,strlen(szBuf),"127.0.0.1",9000);
					}
					return 0;
				}
					  
				四、结束语
				欢迎对代码不足之处提出宝贵意见。wnh5@tom.com 
				 
							

相关资源