首页
社区
课程
招聘
[原创]小弟写了个东西。
发表于: 2012-6-19 22:15 8902

[原创]小弟写了个东西。

2012-6-19 22:15
8902
小弟写了一个简单的网络类,可惜没有人使用;不知道看雪论坛上有没同行的哥哥姐姐们经常写网络方面相关的程序,如果有经常写网络方面的东西不知道对我这个白菜东西感不感兴趣。如果有人愿意使用小弟写的东西(不收费),小弟愿意免费根据各位哥哥姐姐的需求更新
补充:小弟把send recv这些函数给封装了,如果大家有什么好的建议,可以说下。谢谢各位哥哥姐姐支持。说明文档等小弟感觉封装完整后再附上,谢谢各位哥哥姐姐支持。
小弟愿意在此基础上继续开发,希望各位哥哥姐姐给点意见。求一名稳定的挑错哥哥或姐姐。(小弟愿意免费接受开发定制功能,希望各位哥哥姐姐多多支持)
用法:
		m_Socket.SetSocket(SOCK_STREAM,IPPROTO_IP);
		AfxBeginThread(ServerThread,&m_Socket);    //服务器线程
		m_Socket.Client(8080,"127.0.0.1");         //连接服务器
		SetDlgItemText(IDC_EDIT3,TEXT("连接服务器成功"));

线程函数:
	CSocket * pSocket = (CSocket * )pParam; 
	pSocket->Server(8080,255);

演示(按钮代码):
	CString strMsg;
	char szBuffer[MAX_PATH] = {0};
	char szMsg[MAX_PATH] = {0};
	SetDlgItemText(IDC_EDIT1,szMsg);
	SetDlgItemText(IDC_EDIT3,szMsg);
	GetDlgItemText(IDC_EDIT2,strMsg);
//我说
	m_Socket.IsServer(TRUE);                                        //设置当前模式为客户端
	m_Socket.Send(strMsg.GetBuffer(MAX_PATH),strMsg.GetLength(),0); //发送到服务器
//服务端响应
	m_Socket.IsServer(FALSE);                                       //设置当前模式为服务器
	m_Socket.Recv(szMsg,MAX_PATH,0);                                //服务器响应
	wsprintf(szBuffer,"127.0.0.1:%s\r\n",szMsg);
	SetDlgItemText(IDC_EDIT1,szBuffer);
	memset(szMsg,0,MAX_PATH);
	memset(szBuffer,0,MAX_PATH);
//服务器说
	m_Socket.Send("服务器说:好啦,知道啦!",lstrlen("服务器说:好啦,知道啦!"),0);//服务器反馈数据
	m_Socket.IsServer(TRUE);                                        //设置当前模式为客户端
//我响应服务器
	m_Socket.Recv(szMsg,MAX_PATH,0);                                //客户端响应
	SetDlgItemText(IDC_EDIT3,szMsg);
	memset(szMsg,0,MAX_PATH);
	SetDlgItemText(IDC_EDIT2,szMsg);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (20)
雪    币: 120
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
来点介绍,,我想试试。。。:)
2012-6-19 22:18
0
雪    币: 316
活跃值: (128)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
就一个网络类,目前实现了最基本的功能,还在努力构造。求各位哥哥姐姐支持。
2012-6-19 22:22
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
4
怎么也得展示下功能啊。大家看得云里雾里的都不知道你那是啥好东西。
2012-6-19 22:22
0
雪    币: 10
活跃值: (231)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
写个说明文档好么,封装的好还是不错的。
2012-6-19 22:50
0
雪    币: 316
活跃值: (128)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
6
大家有什么好的建议可以和小弟说下,小弟愿意效犬马之劳。说明文档等等写上。
2012-6-19 22:55
0
雪    币: 316
活跃值: (128)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
7
附件已经附上,小弟愿意在此基础上继续开发,希望各位哥哥姐姐给点意见。求一名稳定的挑错哥哥或姐姐。
2012-6-20 02:11
0
雪    币: 116
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不错,起码比MFC自己封装的CSocket好。
2012-6-20 08:52
0
雪    币: 239
活跃值: (190)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
9
说实话的,楼主封闭得不是很好,不知道你平时写网络程序不?一个成熟的网络程序员,封装出来的东西,应该不是这么简单。。

不是打击你,你封装和真的不好,还不如直接使用socket来写,

不过,你的精神可佳,
随便秀一下我封装的吧,给你参考一下:
我封装的这个,是阻塞式操作,还有异步操作和IOCP等封装就不发上来了,

/***********************************************************************
版权所有:choday
文件名称:XSocket.h
描    述:基本socket封
作    者:choday  
创建日期:2011-10-17 17:08:58
修 改 人:choday
修改日期:
修改原因:
***********************************************************************/

#pragma once
#ifndef SOCKETX_H
#define SOCKETX_H

#ifndef _WINSOCK2API_

#ifdef _WINDOWS_
#	ifndef WIN32_LEAN_AND_MEAN
	#error >>>>>>>>> you must define WIN32_LEAN_AND_MEAN before include <windows.h>  <<<<<<<<
#	endif
#endif
#include <winsock2.h>
#endif

namespace XLIB
{

/*
#ifndef _WINSOCK2API_

typedef struct sockaddr SOCKADDR;
typedef unsigned int SOCKET;

#define SOCK_STREAM     1 
#define IPPROTO_TCP      6

#ifndef SOMAXCONN
#define SOMAXCONN       0x7fffffff
#endif

#endif 
*/
class CXSocket  
{
public:
	CXSocket();
	~CXSocket();

	static VOID		Initialize();
	static VOID		UnInitialize();
	static DWORD	GetHostIPv4( const char* hostname );
	static VOID		ParserString( LPCTSTR lpAddress,SOCKADDR* name,int namelen);

	VOID	Attach( SOCKET	hSocket );
	VOID	Dettach();
	SOCKET	GetHandle(){ return m_hSocket;}

	BOOL	Create( int type = SOCK_STREAM ,int protocol = IPPROTO_TCP );//SOCK_DGRAM,IPPROTO_UDP 
	VOID	Close();

	//socket 参数设置
	BOOL	SetRecvTimeOut( DWORD dwTimeOut );
	BOOL	SetSendTimeOut( DWORD dwTimeOut );
	BOOL	SelectForRead( DWORD dwTimeOut = 0);//是否可以读数据了,单位毫秒
	BOOL	SelectForWrite( DWORD dwTimeOut = 0);//是否可以写数据了,单位毫秒
	VOID	DisableUDPReset();				//说明见CPP
	VOID	EnableUDPBroadcast( BOOL Enable = TRUE );
	BOOL	EnableBlockingMode( BOOL Enable = TRUE );//设置为阻塞模式
	BOOL	EnableReuseAddr( BOOL Enable = TRUE );//设置为端口重用模式
	BOOL	EnableKeepAlive( BOOL Enable,DWORD AliveTime = 60*2,DWORD IntervalTime=60*4 );//TCP存活保持,,单位毫秒,AliveTime毫秒后开始自动发送存活包,如果没有收到返回包,将在间隔IntervalTime毫秒后重发

	//获取socket绑定地址

	BOOL	GetSockName( SOCKADDR* pname,int *namelen = 0);
	BOOL	GetPeerName( SOCKADDR* pname,int *namelen = 0);

	//绑定
	BOOL	Bind(const SOCKADDR *pAddr,int naddrlen = 0);
	BOOL	Bind( DWORD dwIP,USHORT uPort );//uPort网络顺序,如果端口是89,应该写htons(89)转换成网络顺序
	BOOL	Bind( int nPort = 0 );//一般顺序,端口89,就写89

	//监听
	BOOL	Listen( int backlog = SOMAXCONN );

	//接受连接
	SOCKET	Accept(SOCKADDR* pAddr,int naddrlen = 0 );
	SOCKET	Accept(DWORD *pRemoteIP = 0,USHORT *pPort = 0);

	//发起连接
	BOOL	Connect( const SOCKADDR* paddr,int naddrlen = 0 );
	BOOL	Connect( DWORD dwRemoteIP,USHORT uPort );//uPort网络顺序
	BOOL	Connect( const char* lpszRemotehost,int nPort );//
	int		GetConnectTime();

	//数据读写
	int		Send( LPCVOID lpbuffer,int nlen );//失败返回0
	int		Recv( LPVOID lpbuffer,int nlen,int flags=0 );//失败返回0

	int		SendBlock( LPCVOID lpbuffer,int nlen);	//发送一个数据块,直接到nlen数据发送完才返回//失败返回0
	int		RecvBlock( LPVOID lpbuffer,int nlen);	//接收一个数据块,直到将缓冲区占满才返回//失败返回0

	int		SendTo( LPCVOID lpbuffer,int nlen,const SOCKADDR* pSendToAddr,int naddrlen = 0,int flags=0 );//失败返回0
	int		RecvFrom( LPVOID lpbuffer,int nlen,SOCKADDR* pRecvFromAddr,int flags=0 );//失败返回0

protected:
	SOCKET	m_hSocket;

	struct tcp_keepalive {
		ULONG onoff;
		ULONG keepalivetime;
		ULONG keepaliveinterval;
	};
	#define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)

};

}
#endif



/***********************************************************************
版权所有:choday
文件名称:XSocket.cpp
描    述:
作    者:choday  
创建日期:2011-10-17 17:07:10
修 改 人:choday
修改日期:
修改原因:
***********************************************************************/

#include "stdafx.h"
#include <winsock2.h>
#include <Mstcpip.h>
#include "SocketX.h"

namespace XLIB
{
#pragma comment( lib,"ws2_32.lib")

#ifndef SIO_UDP_CONNRESET
#define IOC_VENDOR 0x18000000 
#define _WSAIOW(x,y) (IOC_IN|(x)|(y)) 
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif

CXSocket::CXSocket()
{

	Initialize();
	m_hSocket = INVALID_SOCKET;
}

CXSocket::~CXSocket()
{
	UnInitialize();
	m_hSocket = INVALID_SOCKET;
}

VOID CXSocket::Initialize()
{
	WSADATA wsaData;
 	WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
}

VOID CXSocket::UnInitialize()
{
	WSACleanup();	
}

VOID CXSocket::ParserString( LPCTSTR lpAddress,SOCKADDR* name,int namelen)
{
	char	host[64] = {0};

	ZeroMemory( name,namelen);
	name->sa_family = AF_INET;
	for( int i = 0;i<lstrlen(lpAddress)&&i<64;i++)
	{
		
		if( ':' == lpAddress[i] )
		{
			
			LPSOCKADDR_IN(name)->sin_port = htons( _ttoi(&lpAddress[i+1]) );
			LPSOCKADDR_IN(name)->sin_addr.S_un.S_addr = GetHostIPv4(host);
			break;
		}
		host[i] = (char)lpAddress[i];
	}
}

DWORD CXSocket::GetHostIPv4( const char* host_name )
{
	struct hostent *remoteHost;
	struct in_addr addr;

	if(isalpha(host_name[0])) 
	{        /* host address is a name */
		remoteHost = gethostbyname(host_name);
	} 
	else 
	{
		addr.s_addr = inet_addr(host_name);
        return addr.s_addr;
    }

    if (remoteHost == NULL) 
	{
		return 0;
    } else 
	{
		/*
        printf("Function returned:\n");
        printf("\tOfficial name: %s\n", remoteHost->h_name);
        printf("\tAlternate names: %s\n", remoteHost->h_aliases);
        printf("\tAddress type: ");
        switch (remoteHost->h_addrtype) {
        case AF_INET:
            printf("AF_INET\n");
            break;
        case AF_INET6:
            printf("AF_INET\n");
            break;
        case AF_NETBIOS:
            printf("AF_NETBIOS\n");
            break;
        default:
            printf(" %d\n", remoteHost->h_addrtype);
            break;
        }
        printf("\tAddress length: %d\n", remoteHost->h_length);
		*/
        return *(DWORD *)remoteHost->h_addr_list[0];
    }

    return addr.s_addr;
}

VOID CXSocket::Attach( SOCKET	hSocket )
{
	m_hSocket = hSocket;
}

VOID CXSocket::Dettach()
{
	m_hSocket = INVALID_SOCKET;
}

BOOL CXSocket::Create( int type ,int protocol )
{
	m_hSocket = socket( AF_INET,type,protocol );
	if( INVALID_SOCKET == m_hSocket )return FALSE;

	DisableUDPReset();

	return TRUE;
}

VOID CXSocket::Close()
{
	if( INVALID_SOCKET!=m_hSocket )closesocket(m_hSocket);
	m_hSocket = INVALID_SOCKET;
}

BOOL CXSocket::Bind(const SOCKADDR* pAddr,int naddrlen )
{
	if( 0 == naddrlen ) naddrlen = sizeof(SOCKADDR);
	if( SOCKET_ERROR == bind( m_hSocket,(const SOCKADDR*)pAddr,naddrlen ) )return FALSE;

	return TRUE;
}

BOOL CXSocket::Bind( DWORD dwIP,USHORT uPort )
{
	sockaddr_in addr;

	ZeroMemory( &addr,sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr = dwIP;
	addr.sin_port = uPort;

	return Bind((const SOCKADDR*)&addr);
}

BOOL CXSocket::Bind( int nPort )
{
	return Bind(0,htons(nPort));
}//一般顺序,端口89,就写89

BOOL CXSocket::SetRecvTimeOut( DWORD dwTimeOut )
{
	int timeout = dwTimeOut ;
	int optlen = sizeof(optlen); 
	int nRet;

	nRet = setsockopt( m_hSocket, SOL_SOCKET, SO_RCVTIMEO ,(const char *)&timeout, optlen);
	if( -1 == nRet )return FALSE;

	return TRUE;
}


BOOL CXSocket::SetSendTimeOut( DWORD dwTimeOut )
{
	int timeout = dwTimeOut ;
	int optlen = sizeof(optlen); 
	int nRet;

	nRet = setsockopt( m_hSocket, SOL_SOCKET, SO_SNDTIMEO ,(const char *)&timeout, optlen); 
	if( -1 == nRet )return FALSE;

	return TRUE;
}

BOOL CXSocket::SelectForRead( DWORD dwTimeOut )
{	
	TIMEVAL time;
	fd_set  fread;
	int		nRet;

	time.tv_sec = dwTimeOut/1000;
	time.tv_usec = 0;

	FD_ZERO(&fread);
	FD_SET( m_hSocket,&fread);

	nRet = select( 0,&fread,0,0,&time );
	if( nRet <= 0 )return FALSE;

	return TRUE;
}

BOOL CXSocket::SelectForWrite( DWORD dwTimeOut )
{	
	TIMEVAL time;
	fd_set  fwrite;
	int		nRet;

	time.tv_sec = dwTimeOut/1000;
	time.tv_usec = 0;

	FD_ZERO(&fwrite);
	FD_SET( m_hSocket,&fwrite);

	nRet = select( 0,0,&fwrite,0,&time );
	if( nRet <= 0 )return FALSE;

	return TRUE;
}
BOOL CXSocket::Listen( int backlog )
{
	if( SOCKET_ERROR == listen( m_hSocket,backlog ) )return FALSE;

	return TRUE;
}


SOCKET CXSocket::Accept(DWORD *pRemoteIP,USHORT *pPort)
{
	DWORD RemoteIP = 0;
	USHORT Port = 0;
	SOCKET	s;
	sockaddr_in addr;
	int nLen;

	if( pRemoteIP ) RemoteIP = *pRemoteIP;
	if( pPort ) Port = *pPort;

	ZeroMemory( &addr,sizeof(addr));
	addr.sin_family = AF_INET;
	
	nLen = sizeof(SOCKADDR);

	s = accept( m_hSocket,(SOCKADDR*)&addr,&nLen );

	if( pRemoteIP ) *pRemoteIP = addr.sin_addr.S_un.S_addr;
	if( pPort ) *pPort = addr.sin_port;

	return s;
}

SOCKET CXSocket::Accept( SOCKADDR* pAddr,int naddrlen )
{
	SOCKET	s;

	if( 0 == naddrlen ) naddrlen = sizeof(SOCKADDR);
	s = accept( m_hSocket,(SOCKADDR*)pAddr,&naddrlen );
	return s;
}

BOOL CXSocket::Connect( const SOCKADDR* paddr,int naddrlen )
{
	if( 0 == naddrlen ) naddrlen = sizeof(SOCKADDR);
	if( SOCKET_ERROR == connect( m_hSocket,paddr,naddrlen ) )return FALSE;

	return TRUE;	
}


BOOL CXSocket::Connect( DWORD dwRemoteIP,USHORT uPort )
{
	sockaddr_in addr;

	ZeroMemory( &addr,sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr = dwRemoteIP;
	addr.sin_port = uPort;

	return Connect( (const SOCKADDR*)&addr );
}
	
BOOL CXSocket::Connect( const char* lpszRemotehost,int nPort )
{
	return Connect( GetHostIPv4(lpszRemotehost),htons(nPort) );
}

int CXSocket::GetConnectTime()
{
	int nValue = 0;
	int nLength = sizeof(nValue);

	//#define SO_CONNECT_TIME             0x700C
	
	int nRet = getsockopt( m_hSocket, SOL_SOCKET, 0x700C,(char *)&nValue,(PINT)&nLength );
	if( -1 == nRet || -1 == nValue )return FALSE;

	return nValue;
}

int	CXSocket::Send( LPCVOID lpbuffer,int nlen )
{
	int		nRet;

	nRet = send( m_hSocket,(const char*)lpbuffer,nlen,0 );
	if( SOCKET_ERROR == nRet )return 0;

	return nRet;
}

int	CXSocket::Recv( LPVOID lpbuffer,int nlen,int flags )
{
	int		nRet;

	nRet = recv( m_hSocket,(char*)lpbuffer,nlen,flags );
	if( SOCKET_ERROR == nRet )return 0;

	return nRet;
}
	
int	CXSocket::SendBlock( LPCVOID lpbuffer,int nlen)
{
	int		nRet;	
	int		TotalLen = nlen;
	int		nSentBytes = 0;
	LPBYTE	lpByter = (LPBYTE)lpbuffer;

	while( TotalLen > 0 )
	{
		nRet = Send( &lpByter[nSentBytes],TotalLen );
		if( 0 == nRet )break;
	
		nSentBytes += nRet;
		TotalLen -= nRet;
	}

	return nSentBytes;
}

int	CXSocket::RecvBlock(LPVOID lpbuffer,int nlen)
{
	int		nRet;	
	int		TotalLen = nlen;
	int		nRecvBytes = 0;
	LPBYTE	lpBytes = (LPBYTE)lpbuffer;

	while( TotalLen > 0 )
	{
		nRet = Recv( &lpBytes[nRecvBytes],TotalLen );
		if( 0 == nRet )break;
	
		nRecvBytes += nRet;
		TotalLen -= nRet;
	}

	return nRecvBytes;
}

int	CXSocket::SendTo( LPCVOID lpbuffer,int nlen,const SOCKADDR* pSendToAddr,int naddrlen,int flags )
{
	int		nRet;

	if( 0 == naddrlen ) naddrlen = sizeof(SOCKADDR);
	nRet = sendto( m_hSocket,(const char*)lpbuffer,nlen,flags,(const SOCKADDR*)pSendToAddr,naddrlen );
	if( SOCKET_ERROR == nRet )return 0;

	return nRet;
}

int	CXSocket::RecvFrom( LPVOID lpbuffer,int nlen,SOCKADDR* pRecvFromAddr,int flags )
{
	int		nRet;
	int		Namelen = sizeof(SOCKADDR);
	SOCKADDR addr;

	ZeroMemory( &addr,sizeof(addr) );
	addr.sa_family = AF_INET;

	if( 0 == pRecvFromAddr )pRecvFromAddr=&addr;

	nRet = recvfrom( m_hSocket,(char*)lpbuffer,nlen,flags,(SOCKADDR*)pRecvFromAddr,&Namelen );
	if( SOCKET_ERROR == nRet )return 0;

	return nRet;
}


/*
今天team里同事在Windows XP下调一个UDP server时发现recvfrom会返回WSAECONNRESET。以前没出现过这个问题。后来在网上查了一下把问题解决了,做个笔记。

原因:server用同一个udp socket来发送和接收,发送和接收在不同的线程里进行。启动时,接收线程会在recvfrom阻塞,发送线程向远端host的ip和端口发送数据,若此ip存在且没有程序打开此端口,该host可能会返回icmp的port reachable消息(自己猜的),把socket置为错误状态,从而导致recvfrom返回错误WSAECONNRESET。
*/
VOID CXSocket::DisableUDPReset()
{
	BOOL   bNewBehavior   =   FALSE;   
	DWORD   dwBytesReturned; 
	WSAIoctl( m_hSocket,SIO_UDP_CONNRESET,&bNewBehavior,sizeof(bNewBehavior),NULL,0,&dwBytesReturned,NULL,NULL);
}

VOID CXSocket::EnableUDPBroadcast( BOOL Enable )
{
	int iOptionValue = (int)Enable;
	setsockopt( m_hSocket,SOL_SOCKET,SO_BROADCAST, (const char*)&iOptionValue, sizeof(int)); 
}

BOOL CXSocket::EnableBlockingMode( BOOL Enable )
{
//-------------------------
// Set the socket I/O mode: In this case FIONBIO
// enables or disables the blocking mode for the 
// socket based on the numerical value of iMode.
// If iMode = 0, blocking is enabled; 
// If iMode != 0, non-blocking mode is enabled.
	u_long iMode = (u_long)(TRUE==Enable?0:1);
	return -1 != ioctlsocket( m_hSocket, FIONBIO, &iMode);
}

BOOL CXSocket::EnableReuseAddr( BOOL Enable )
{
	int iOptionValue = (int)Enable;
	return -1 != setsockopt( m_hSocket,SOL_SOCKET,SO_REUSEADDR, (const char*)&iOptionValue, sizeof(int)); 
}

BOOL CXSocket::EnableKeepAlive( BOOL Enable,DWORD AliveTime,DWORD IntervalTime )
{


	tcp_keepalive sKA_Settings = {0}, sReturned = {0} ;
	DWORD	dwBytes = 0;
	sKA_Settings.onoff = Enable ;
	sKA_Settings.keepalivetime = AliveTime ; // Keep Alive in 5.5 sec.
	sKA_Settings.keepaliveinterval = IntervalTime ; // Resend if No-Reply 
	if (WSAIoctl( m_hSocket, SIO_KEEPALIVE_VALS, &sKA_Settings,
			  sizeof(sKA_Settings), &sReturned, sizeof(sReturned), &dwBytes,
			  NULL, NULL) == SOCKET_ERROR)
		 {
			   return FALSE;
		 }

	return TRUE;

}
BOOL CXSocket::GetSockName( SOCKADDR* pname,int *namelen)
{
	int len = sizeof(SOCKADDR);
	if( 0 == namelen )namelen = &len;

	return 0 == ::getsockname( m_hSocket,pname,namelen );
}

BOOL CXSocket::GetPeerName( SOCKADDR* pname,int *namelen)
{
	int len = sizeof(SOCKADDR);
	if( 0 == namelen )namelen = &len;

	return 0 == ::getpeername( m_hSocket,pname,namelen );
}

}


2012-6-20 08:59
0
雪    币: 239
活跃值: (190)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
顺便给你挑个错误

在下面的代码中:
错误1==>对主机名转换不正确,不全面

你只判断了lpszHost为www网址的情况 ,没有判断其它的情况 ,比如bbs.pediy.com

如果传入的字符串中没有www的话,你会直接调用inet_addr,这个函数只能用来转换ip地址的字符串,不能将主机名转换成ip地址,

错误2==>你的lpszHost参数类型是LPCTSTR ,如果编译环境为unicode的时候,你的代码将编译通不过,因为inet_addr只接受ansi字符串,所以你的这个是错误的

//创建客户端
int CSocket::Client(UINT nPort, LPCTSTR lpszHost)
{
	if(TRUE != Startup())
	{
		CloseClient();
		throw ECSocket(ECSocket::WSA_VER);
	}
	m_hClientSocket = socket(AF_INET, m_nSockType,m_nProtoType);
	if ( INVALID_SOCKET == m_hClientSocket ) 
	{
		CloseClient();
		throw ECSocket(ECSocket::WSA_INVALID_SOCKET);
    }
	if(NULL != strstr(lpszHost,"www.") || NULL != strstr(lpszHost,"WWW."))
	{
        struct hostent * host = gethostbyname(lpszHost);
		if(NULL != host)
		{
			m_hClientSock.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
		}
		else
		{
			CloseClient();
			throw ECSocket(ECSocket::WSA_GETHOSTBY_NAME_ADDR);
		}
	}
	else
	{
		m_hClientSock.sin_addr.S_un.S_addr = inet_addr(lpszHost);
	}
	m_hClientSock.sin_family = AF_INET;
	m_hClientSock.sin_port = htons(nPort);
	if( SOCKET_ERROR == connect(m_hClientSocket,(SOCKADDR*)&m_hClientSock,sizeof(m_hClientSock)))
	{
		CloseClient();
		throw ECSocket(ECSocket::WSA_CONNECT);
	}
	return 0;
}
2012-6-20 09:18
0
雪    币: 5047
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习啦,谢谢分享.
2012-6-20 09:21
0
雪    币: 347
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
支持下
感谢楼主~
2012-6-20 09:22
0
雪    币: 94
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
网络类windows下感觉还是用完成端口封装实现比较好,再结合线程池与内存池,作为网络服务器有很高的并发性
至于客户端嘛,简单的事件通知模型应该就能满足需要了
2012-6-20 09:26
0
雪    币: 239
活跃值: (190)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
14
还有一个问题,你的这个封装类 没有处理 TCP粘包和裂包的能力.
如果使用你的这个东西,我先取得数据包的大小,然后在读指定大小的数据块的时候,我还得分多次去读,我还得自己判断读了多少数据,还得跟据具体情况去组包和分包

解决方案
详情请参考我的CXSocket::RecvBlock接收一个指定大小的块
如果取得了数据包大小,直接调用CXSocket::RecvBloc便可一次性读取一个数据块,只有成功或者失败,不需要你去组包或者分包。如果你读取的数量不是你指定的数量,则socket已失效。

总结:
你对tcp协议了解不够,tcp是流式数据,像水流一样,你一次性倒进了多少水,再一次性取出来的水量,不 一定是你倒进的水量,你得分多次去取水,才能取出倒进去的水量

在tcp中,有可能发生这以下情况

如果先发送1000个字节的数据包,再发送500字节的数据包

在接收端有可能会随机 出现 以下情况 ,

1裂包,先收到<1000个字节,你得再去读取剩下的数据,组成 1000字节的包
2粘包,一次性收到>1000个字节,你得把后面的部分去掉,让前面1000个字节组成一个包,剩下的部分,和下次收到的数据,组成500个字节的包
2012-6-20 09:30
0
雪    币: 90
活跃值: (91)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
学习了 网络编程比较难
2012-6-20 09:44
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
16
choday解说得很精彩
2012-6-20 09:50
0
雪    币: 316
活跃值: (128)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
17
感谢哥哥你给的意见,晚上回去参考你的再修改修改
2012-6-20 09:53
0
雪    币: 120
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
学习。。。。
2012-6-20 10:01
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19
我觉得 disable udp connection reset 有点不妥,为什么要disable这个呢,这个是正常的连接错误,你发送一个数据报到对方没有进程监听的端口,对方主机返回一个端口不可达的icmp差错报文,而IP层在收到该报文后,给上层(TCP或UDP)返回一个RST,标示该连接被重置,而此时,windows和linux下实现是不一样的,linux 的实现是根据RFC的要求,如果连接被重置,那么该socket的read或者recv返回-1,而send或者wirte直接就core dump了(这个能避免),windows比较扯淡,完全不按标准来,自己想怎么实现就怎么实现,有些windows server 收到端口不可达和主机不可达不给应用层通知,都作主机不可达处理,端口不可达可以定义为连接错误,而主机不可达,可能由于网络的故障,中间某个路由器短时间能恢复,那么连接此时应该能正常恢复的的。而windows server间隔10秒重传一次SYN就放弃,实在是懒惰加扯淡。

至于测试程序,见这篇文章http://ayufox.iteye.com/blog/657636
2012-6-20 10:16
0
雪    币: 239
活跃值: (190)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
20
disable udp connection reset是一个可选项,你可以修改一下,
但是修改了会有一个问题,如果一个主机要给多个主要使用此socket来发送的话,如果其中一个主机断线,将会导致你的socket失效,是socket失效,不只是WSARecvFROM返回错误 (winxpsp3下测试结果 ,不知道服务器上什么情况 ),也就是说,你将会收不到其它主机发来的数据包,
2012-6-21 09:01
0
雪    币: 316
活跃值: (128)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
21
感谢2位大哥为了小弟进行讨论,感谢。
2012-6-21 10:52
0
游客
登录 | 注册 方可回帖
返回
//