请问:client 正在connect()的时候,如何取消连接请求?就像MSN,QQ的登陆一样,正在登陆的时候用户是可以随时“取消登陆”的,但此时程序一般都是在connect()服务器啊,在没有知道是否登陆成功的时候如何断开SOCKET呢?
解决方案 »
- 光棍节的故事!
- 重绘listbox遇到个问题向大家请教
- 线程关闭的基础问题
- VC 2008里面,“Project”菜单下的“Add Web Reference”项是灰掉的,如何解决?
- 数据库链接问题(DAO方面的,有两句代码需要请分析)
- 求精确获得时间的办法
- 数据库查询问题(有点难度)
- 那位达人详细RECT的解释,如果超出屏范围改怎么处理?如何用它来表示不规则图形?
- 关于Tree Control的简单问题???
- 菜鸟问题(一):用F10可以跟踪到WinMain,可找不到他在那个文件里?
- 高分求助:如何解决splitterwnd中的view闪烁问题?200分!
- windows2003 soft-ice
该函数的原型为:
int shutdown( SOCKET s, int how );
其中how的取值为:SD_RECEIVE、SD_SEND或SD_BOTH,若是SD_RECEIVE就表示不允许在调用接收函数,这对底部的协议层没影响,若是SD_SEND表示不在调用发送,最后参数表示取消2端的操作。
注意:该函数并不关闭套接字,并且套接字的资源一直保持到closesocket()调用。
另外一个函数是:closesocket( SOCKET s )这个才是真正的关闭SOCKET。
//
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "BdSockEx.h"#pragma comment(lib,"Ws2_32.lib")
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////CBdSockEx::CBdSockEx()
{
Reset();
}CBdSockEx::CBdSockEx(SOCKET Socket)
{
Reset();
m_Socket=Socket;
}CBdSockEx::~CBdSockEx()
{
}bool CBdSockEx::Startup(void)
{
WSADATA wsd;
if (WSAStartup(MAKEWORD(1,1), &wsd) != 0)
{
AfxMessageBox("Failed to load Winsock library!\n");
return false;
}
return true;
}void CBdSockEx::Cleanup(void)
{
WSACleanup();
}bool CBdSockEx::IsConnected(void)
{
return(m_nStatus==BDSOCK_STAT_CONNECTED);
}bool CBdSockEx::IsDisConnected(void)
{
return(m_dwErrNo==BDSOCK_ERRNO_DISCONNECT);
}void CBdSockEx::Reset(void)
{
m_dwErrNo=BDSOCK_ERRNO_NONE;
m_dwSubErrNo=BDSOCK_ERRNO_NONE;
m_nStatus=BDSOCK_STAT_NOCONNECT;
m_Socket=INVALID_SOCKET;
}bool CBdSockEx::Create(void)
{
m_Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_Socket==INVALID_SOCKET)
{
m_dwErrNo=BDSOCK_ERRNO_CREATE;
return false;
}
//设为非阻塞
u_long ofcmode=1;
if(ioctlsocket(m_Socket,FIONBIO,&ofcmode) )
{
m_dwErrNo=BDSOCK_ERRNO_CREATE;
return false;
}
return true;
}int CBdSockEx::SignalSafeSelect(int nfds, fd_set * rs, fd_set * ws, fd_set * es,struct timeval *tv)
{
int rv;
while ((rv = select (nfds, rs, ws, es, tv)) < 0)
{
int nError=WSAGetLastError();
if(nError!=WSAEINTR)
break;
}
return rv;
}void CBdSockEx::MsToTimeval (const int ms, struct timeval *tv)
{
tv->tv_sec = ms / TIME_CNV_RATIO;
tv->tv_usec = (ms - tv->tv_sec * TIME_CNV_RATIO) * TIME_CNV_RATIO;
}bool CBdSockEx::Connect(char * szIpAddr,UINT nPort,int nSec)
{
struct sockaddr_in srvaddr;
memset(&srvaddr,0x00,sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(nPort);
srvaddr.sin_addr.s_addr = inet_addr(szIpAddr);
int retcode = connect(m_Socket, (struct sockaddr*)&srvaddr, sizeof(srvaddr));
if(retcode==0)
{ //超时处理
AfxMessageBox("retcode==0\n");
return false;
}
/*******
int nError=WSAGetLastError();
printf("nError=%ld\n",nError);
if(nError!=WSAEWOULDBLOCK)
{
return false;
}
*********/
struct timeval tv;
fd_set readfds,writefds;
tv.tv_sec = nSec; //设置时间为5秒
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(m_Socket,&writefds);
retcode =SignalSafeSelect(m_Socket+1,0, &writefds,0, &tv);
if (retcode < 0)
{ //select返回错误???
//错误处理
m_dwErrNo=BDSOCK_ERRNO_CONNECT;
return false;
}
else if(0 == retcode)
{ //超时处理
AfxMessageBox("connect timeout!\n");
m_dwErrNo=BDSOCK_ERRNO_CONNECT;
return false;
}
//套接字已经准备好
if ( !FD_ISSET(m_Socket, &readfds) && !FD_ISSET(m_Socket, &writefds))
{
AfxMessageBox("!FD_ISSET(m_Socket, &readfds) && !FD_ISSET(m_Socket, &writefds)\n");
m_dwErrNo=BDSOCK_ERRNO_CONNECT;
return false;
}
int err,len=sizeof(int);
if (getsockopt(m_Socket, SOL_SOCKET, SO_ERROR, (char *)&err, &len) < 0)
{
AfxMessageBox("getsockopt(m_Socket, SOL_SOCKET, SO_ERROR, (char *)&err, &len) < 0\n");
m_dwErrNo=BDSOCK_ERRNO_CONNECT;
return false;
}
if (err != 0)
{
AfxMessageBox("err !=0\n");
m_dwErrNo=BDSOCK_ERRNO_CONNECT;
return false;
}
AfxMessageBox("connect return ok!\n");
m_nStatus=BDSOCK_STAT_CONNECTED;
return true;
}void CBdSockEx::Close(void)
{
if(m_Socket!=INVALID_SOCKET)
{
if(m_nStatus==BDSOCK_STAT_CONNECTED)
{
shutdown(m_Socket,SD_BOTH);
}
closesocket(m_Socket);
}
Reset();
}int CBdSockEx::Read(char * szBuf,int nLength,int msec)
{
struct timeval tv;
fd_set readfds;
MsToTimeval (msec, &tv);
FD_ZERO(&readfds);
FD_SET(m_Socket,&readfds);
int retcode =SignalSafeSelect(m_Socket+1,&readfds,0,0, &tv);
if (retcode < 0)
{
AfxMessageBox("read select<0\n");
return 0;
}
else if(0 == retcode)
{
AfxMessageBox("read select=0\n");
return 0;
}
if(FD_ISSET(m_Socket,&readfds))
{
int nRet=recv(m_Socket,szBuf,nLength,0);
if(nRet>0)
{
szBuf[nRet]=0x00;
return nRet;
}
int nError=WSAGetLastError();
if(nError!=WSAEINTR || (nRet==0))
{
m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;
return -1;
}
AfxMessageBox("read ret %d error=%d\n",nRet,nError);
return 0;
}
m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;
return -1;
}int CBdSockEx::Write(char * szBuf,int nLength,int msec)
{
struct timeval tv;
fd_set writefds;
MsToTimeval (msec, &tv);
FD_ZERO(&writefds);
FD_SET(m_Socket,&writefds);
int retcode =SignalSafeSelect(m_Socket+1,0,&writefds,0, &tv);
if (retcode < 0)
{
AfxMessageBox("write select<0\n");
return 0;
}
else if(0 == retcode)
{
AfxMessageBox("write select=0\n");
return 0;
}
if (FD_ISSET(m_Socket,&writefds))
{
int wc = send (m_Socket,szBuf,nLength,0);
if(wc>0)
{
return wc;
}
int nError=WSAGetLastError();
if(nError!=WSAEINTR || (wc==0))
{
m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;
return -1;
}
AfxMessageBox("write error=%d\n",nError);
return 0;
}
m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;
return -1;
}
SOCKET CBdSockEx::Accept(
struct sockaddr FAR * cliaddr,//ip地址
int FAR * addrlen,
int nSec
)
{
int n;
fd_set rset;
SOCKET socket=INVALID_SOCKET;
struct timeval tv;
tv.tv_sec=nSec;
tv.tv_usec=0;
FD_ZERO (&rset);
FD_SET(m_Socket,&rset);
n = SignalSafeSelect(m_Socket+ 1, &rset, NULL, NULL, &tv);
if(n < 0)
{
m_dwErrNo=BDSOCK_ERRNO_ACCEPT;
return INVALID_SOCKET;
}
if (FD_ISSET(m_Socket, &rset))
{
while ((socket = accept(m_Socket, cliaddr, addrlen))==INVALID_SOCKET)
{
int nError=WSAGetLastError();
if (nError != WSAEWOULDBLOCK && nError!= WSAECONNABORTED && nError!= WSAEINTR)
{
m_dwErrNo=BDSOCK_ERRNO_ACCEPT;
break;
}
}
}
return socket;
}bool CBdSockEx::Listen(int nMaxClient)
{
int nRet=listen(m_Socket,nMaxClient);
if(nRet== SOCKET_ERROR)
{
m_dwErrNo=BDSOCK_ERRNO_LISTEN;
return false;
}
return true;
}bool CBdSockEx::Bind(char * szLocalIpAddr,UINT nPort)
{
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(szLocalIpAddr);
service.sin_port = htons(nPort);
if(bind(m_Socket,(SOCKADDR*) &service,sizeof(service)) == SOCKET_ERROR)
{
int nError=WSAGetLastError();
printf("nError=%d\n",nError);
m_dwErrNo=BDSOCK_ERRNO_BIND;
return false;
}
return true;
}
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_BDSOCKEX_H__7B57E28E_05F0_5688_956AD_B93BC30025F897__INCLUDED_)
#define AFX_BDSOCKEX_H__7B57E28E_05F0_5688_956AD_B93BC30025F897__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <winsock2.h>#define TIME_CNV_RATIO 1000
class CBdSockEx
{
private:
SOCKET m_Socket;public:
CBdSockEx();
CBdSockEx(SOCKET Socket);
virtual ~CBdSockEx(); unsigned long m_dwErrNo; //错误码
unsigned long m_dwSubErrNo;
int m_nStatus; //连接状态 static bool Startup(void);
static void Cleanup(void);
void Reset(void);
bool IsConnected(void);
bool IsDisConnected(void); bool Create(void);
void Close(void);
bool Bind(char * szLocalIpAddr,UINT nPort);
bool Listen(int nMaxClient=5);
SOCKET Accept(struct sockaddr FAR * cliaddr,int FAR * addrlen,int nSec=3); bool Connect(char * szIpAddr,UINT nPort,int nSec=5); int Read(char * szBuf,int nLength,int msec=50);
int Write(char * szBuf,int nLength,int msec=50);private:
int SignalSafeSelect(int nfds, fd_set * rs, fd_set * ws, fd_set * es,struct timeval *tv);
void MsToTimeval(const int ms, struct timeval *tv);
}; #endif // !defined(AFX_BDSOCKEX_H__7B57E28E_05F0_5688_956AD_B93BC30025F897__INCLUDED_)