完成端口模式的accept问题

D0ckLng 2010-04-29 03:42:36
主体上完成端口可以工作了.我打算让它可以暂停ACCEPT.
于是暂停的时候,不再调用ACCEPT().
结果是客户端仍然CONNECT()成功,发数据SEND()成功,数据全部发出.
猜想可能是暂停以后上一次的ACCEPT()还没返回,继续开客户端,同上.同上..同上...
服务端确实没有调ACCEPT().继续服务以后可以ACCEPT到之前开的SOCKET.
服务端LISTEN的BACKLOG参数(2参)是10,改0也一样.
问题可能出在哪了?
我希望是暂停以后IOCP服务可以很干脆的拒绝掉新连接.
...全文
343 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaomi_428 2010-04-30
  • 打赏
  • 举报
回复
先留一个脚印出来
zhou1xp 2010-04-30
  • 打赏
  • 举报
回复
学习下,最近要写这个了
D0ckLng 2010-04-30
  • 打赏
  • 举报
回复
send 正常啊,发多少就是多少!
send不正常的话我的sendPacket会返回假,或者阻塞在里面
D0ckLng 2010-04-30
  • 打赏
  • 举报
回复
恩..这样就是关机了.
dinona 2010-04-30
  • 打赏
  • 举报
回复
那就关闭侦听端口吧,那以后客户都连不上来了
D0ckLng 2010-04-30
  • 打赏
  • 举报
回复

帮忙解决一下..结果不重要- -
http://topic.csdn.net/u/20100125/10/941f5cc5-bcb8-4226-b3b3-7d2379e249a9.html
D0ckLng 2010-04-30
  • 打赏
  • 举报
回复
accept完之后马上closesocket就好象我总去打电话骚扰某女孩,结果每次她都接了电话马上挂掉.(狠啊..我的话费555~)而她的代价是每次要拿出来看一下号码然后按两个键(接,挂)
不accept的话就相当于每次都不接,但其实通话的链路移动已经帮我们建立好了.而不近人意的是我的电话是完全没有彩铃的,连嘟嘟声都没有,于是我就不管通没通的就开始讲话了..
我想最好的只能是不接电话挂掉,更奢侈的想法是不可能了.
YY了半天..
结论:
 处理对策 1.不接;2.不接直接挂;3.接了挂
 期望是2.没有更好的选择了.实际上用的是3. 
 1?茫茫无尽的等待..
 存在的问题:我的电话连嘟嘟声都没有
dinona 2010-04-30
  • 打赏
  • 举报
回复
服务端LISTEN的BACKLOG参数(2参)是10,改0也一样.
backlog我记得是指三次握手中的等待队列,0应该是没限制的意思
如果你希望实现你要的功能的话,或许我只能这样帮你
accept完之后马上closesocket,呵呵
dinona 2010-04-30
  • 打赏
  • 举报
回复
我帮你测试过,的确是如此,不单单是iocp是这样,其他一般的tcp也一样,
我帮你查了资料得到的理解是:
1.端口(假设s3000)处于listen状态,客户端connect通过三次握手,完成之后就确定两者之间是可通的,也就是说客户察觉到服务器的确开了一个端口在listen,并且我们可以对这个端口进行发送数据;
2.服务器端与客户端的路由表只负责有对应影射出来的端口进行服务,客户端connect成功之后,将一个数据包发送给路由,路由根据对应的路径发出去,路由发觉确实存在这么个端口(s3000),而且是可达的,于是就你的数据包路由出去,于是客户的send成功了.
3.对于服务端,数据包确实已经到达对应端口的协议栈(帮人帮到底,我特地用抓包程序查看过),即使我们没有为客户申请socket资源,连接依然是已经存在的.
4.这样的结果相当于客户端的一相情愿,服务器端根本就不知道这个客户的存在.
ps:我记得打洞技术似乎就是用到这个,你可以参考一下加强理解.
以上言论不具备权威性质,如有误导,请指正
wnx_u 2010-04-30
  • 打赏
  • 举报
回复
好像可以用shutdown(FD_...)
尹成 2010-04-29
  • 打赏
  • 举报
回复
端口处于侦听状态,客户应该是可以connect成功的,但是send肯定不会成功的,查看send的返回值
D0ckLng 2010-04-29
  • 打赏
  • 举报
回复
我的SERVICEMAIN函数
VOID WINAPI __ServiceMain(DWORD dwArgc,LPTSTR* lpszArgv)
{
DWORD InitResult,SpecificError;
m_ServiceStatusHandle = RegisterServiceCtrlHandler(m_ServiceName,(LPHANDLER_FUNCTION)___DONOTCALLTHISFUNCTION_ServiceCtrlHandler);

if (m_ServiceStatusHandle == NULL)
{
return;
}
//SetServiceStatus(ServiceStatusHandle,&ServiceStatus);
// Initialization code goes here. 初始化是IOCP的例行过程
InitResult = myInitialization(dwArgc,lpszArgv, &m_ServiceStatus,SpecificError);

// Handle error condition
if (InitResult != NO_ERROR)
{
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
m_ServiceStatus.dwWin32ExitCode = InitResult;
m_ServiceStatus.dwServiceSpecificExitCode = SpecificError;

::SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus);
return;
}

// Initialization complete - report running status.
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;

//if (!SetServiceStatus (ServiceStatusHandle, &ServiceStatus))
if(!::SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))return;

// This is where the service does its work.
myServiceMainThread();//这个函数就是我贴的第一个函数的全部内容.ACCEPT就是在这个函数里
return;
}

myInitialization
{
int ret;
_dwArgc;
_lpszArgv;

//设置PENDING状态
_pServiceStatus->dwServiceType = SERVICE_WIN32;
_pServiceStatus->dwCurrentState = SERVICE_START_PENDING;
_pServiceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
_pServiceStatus->dwWin32ExitCode = 0;
_pServiceStatus->dwServiceSpecificExitCode = 0;
_pServiceStatus->dwCheckPoint = 1;
_pServiceStatus->dwWaitHint = 1000;
this->SetServiceStatus(_pServiceStatus);

m_hEventAccept = ::CreateEvent(0,TRUE,TRUE,NULL);
if(m_hEventAccept == NULL)
{
return GetLastError();
}

//Create socket
m_ServerSocket = WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, NULL,0,WSA_FLAG_OVERLAPPED);
if(m_ServerSocket == INVALID_SOCKET)
{
_SpecificError = WSAGetLastError();
if(WSANOTINITIALISED == _SpecificError)
{
WSADATA wsaData;
ZeroMemory(&wsaData,sizeof(WSADATA));
if(0 == (_SpecificError = WSAStartup(MAKEWORD(2,2), &wsaData)))
{
isWSAStartupByUs = TRUE;
}
else
{ return ERROR_SERVICE_SPECIFIC_ERROR;}

m_ServerSocket = WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, NULL,0,WSA_FLAG_OVERLAPPED);

}
else
{ return ERROR_SERVICE_SPECIFIC_ERROR;}
}
if( m_ServerSocket == INVALID_SOCKET )
{
_SpecificError = WSAGetLastError();
cout << "Server Socket Creation Failed::Reason Code::" << _SpecificError << endl;
return ERROR_SERVICE_SPECIFIC_ERROR;
}


//bind
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = m_BindAddress;//htonl(m_BindAddress);
service.sin_port = htons(m_ListenPort);//m_ListenPort
ret = bind(m_ServerSocket,(SOCKADDR *)&service,sizeof(service));
if( ret == SOCKET_ERROR )
{
closesocket(m_ServerSocket);
m_ServerSocket = NULL;
_SpecificError = WSAGetLastError();
cout << "Server Soket Bind Failed::Reason Code::"<< _SpecificError << endl;
return ERROR_SERVICE_SPECIFIC_ERROR;
}


//listen
ret = listen(m_ServerSocket, 0);
if( ret == SOCKET_ERROR )
{
closesocket(m_ServerSocket);
m_ServerSocket = NULL;
_SpecificError = WSAGetLastError();
cout << "Server Socket Listen Failed::Reason Code::"<< _SpecificError << endl;
return ERROR_SERVICE_SPECIFIC_ERROR;
}

// Create IOCP
SYSTEM_INFO sysInfo;
ZeroMemory(&sysInfo,sizeof(SYSTEM_INFO));
GetSystemInfo(&sysInfo);
m_ThreadCount = (WORD)sysInfo.dwNumberOfProcessors * 2;
m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,m_ThreadCount);
if (m_hIOCP == NULL)
{
closesocket(m_ServerSocket);
m_ServerSocket = NULL;
_SpecificError = GetLastError();
cout << "CreateIoCompletionPort() Failed::Reason::"<< _SpecificError << endl;
return _SpecificError;
}
if (CreateIoCompletionPort((HANDLE)m_ServerSocket,m_hIOCP,0,0) == NULL)
{
closesocket(m_ServerSocket);
m_ServerSocket = NULL;
CloseHandle(m_hIOCP);
m_hIOCP = NULL;
_SpecificError = GetLastError();
cout << "Binding Server Socket to IO Completion Port Failed::Reason Code::"<< _SpecificError << endl;
return _SpecificError;
}


//Create worker threads
ret = 0;
m_pWorkThread = new CIOCPThread*[m_ThreadCount];
for( WORD dwThread=0; dwThread < m_ThreadCount; dwThread++ )
{
m_pWorkThread[dwThread] = new CIOCPThread(m_hIOCP);

if(m_pWorkThread[dwThread]->Ctrl_turnon())
{
ret++;
}
else
{
delete m_pWorkThread[dwThread];
m_pWorkThread[dwThread] = NULL;
}
}
if(ret == 0)
{
closesocket(m_ServerSocket);
m_ServerSocket = NULL;
CloseHandle(m_hIOCP);
m_hIOCP = NULL;
cout << "Can't Create ANY Thread for work."<< endl;
return ERROR_TOO_MANY_TCBS;//无法创建线程
}
return ERROR_SUCCESS;
}
D0ckLng 2010-04-29
  • 打赏
  • 举报
回复
accept部分,在主线程中
{
SOCKET ls ;
sockaddr_in client;
int addrlen = sizeof(sockaddr_in);

while(WAIT_OBJECT_0 == ::WaitForSingleObject(m_hEventAccept,(DWORD)(-1)))
{//m_hEventAccept是一个手动set,reset的事件
ls = accept( m_ServerSocket, (SOCKADDR *)&client, &addrlen );
//ls = WSAAccept( m_ServerSocket, (SOCKADDR *)&client, &addrlen );
if(ls == SOCKET_ERROR) break;
cout << "Client "<<inet_ntoa(client.sin_addr)<<":"<<ntohs(client.sin_port)<<"connected." << endl;

//diable buffer to improve performance
int nZero = 0;
setsockopt(ls, SOL_SOCKET, SO_SNDBUF, (char *)&nZero, sizeof(nZero));


if (CreateIoCompletionPort((HANDLE)ls,m_hIOCP,0,0) == NULL){
cout << "Binding Client Socket to IO Completion Port Failed::Reason Code::"<< GetLastError() << endl;
closesocket(ls);
}
else { //post a recv request 立即投递一个读请求
IO_DATA * data = new IO_DATA;
ZeroMemory(&data->Overlapped,sizeof(data->Overlapped));
ZeroMemory(data->Buffer,sizeof(data->Buffer));
data->opCode = IO_READ;
// data->nTotalBytes = 0;
// data->nSentBytes = 0;
data->wsabuf.buf = data->Buffer;
data->wsabuf.len = sizeof(data->Buffer);//IOCP_OVERLAPPED_MAXBUFFSIZE;
data->activeSocket = ls;
DWORD dwRecvNumBytes=0,dwFlags=0;
int nRet = WSARecv(ls,&data->wsabuf, 1, &dwRecvNumBytes,
&dwFlags,
&data->Overlapped, NULL);
if(nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
cout << "WSARecv Failed::Reason Code::"<< WSAGetLastError() << endl;
closesocket(ls);
delete data;
}
}
}
}


独立的客户端

bool sendPacket(SOCKET sendSock,char* buf,int sizeofbuf)
{
int cur=0;
int sended;
int toSend;
static DWORD TimetoWait=100;
while(cur<sizeofbuf)
{
toSend = sizeofbuf-cur;
sended = send(sendSock,buf+cur,toSend,0);
if(SOCKET_ERROR == sended)
{
if(sended == WSAEWOULDBLOCK)
{
printf(".");
Sleep(TimetoWait);
TimetoWait+=10;
if(TimetoWait>1000)
{ TimetoWait=1000; }
continue;}
else
{ return false;}
}
else
{
cur+=sended;
TimetoWait-=10;if(TimetoWait<100)TimetoWait=100;
}
}
return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
SOCKET tcpSock;
char desIP[30] = "127.0.0.1";
char staticMsg[250];
DWORD ddesip;
WSADATA wsaData;
int num;

::sprintf(staticMsg,"[%u]",GetCurrentProcessId());

if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{printf("SOCKET fault!application halt!%u\n",GetLastError());return -1;}
ddesip = inet_addr(desIP);
if(INADDR_NONE == ddesip)
{printf("IP invalid~\n");return -2;}
tcpSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(tcpSock == INVALID_SOCKET)
{printf("Create SOCKET failed~%u\n",GetLastError());return -3;}
sockaddr_in sAddr;
sAddr.sin_family = AF_INET;
// sAddr.sin_port = 0;
// sAddr.sin_addr.s_addr = 0;
// if(bind(tcpSock,(struct sockaddr*)&sAddr,sizeof(sAddr))==SOCKET_ERROR)
// {printf("bind SOCKET failed~%u\n",GetLastError());closesocket(tcpSock);return -4;}
sAddr.sin_port = htons(52388);
sAddr.sin_addr.s_addr = ddesip;
if(SOCKET_ERROR == connect(tcpSock,(sockaddr*)&sAddr,sizeof(sockaddr_in)))
{
printf("SOCKET connect port:52388 failed~ try port:52389\n");
sAddr.sin_port = htons(52389);
if(SOCKET_ERROR == connect(tcpSock,(sockaddr*)&sAddr,sizeof(sockaddr_in)))
{printf("SOCKET connect failed~%u\n",GetLastError());closesocket(tcpSock);return -5;}
}

int times = 50;
while(sendPacket(tcpSock,staticMsg,strlen(staticMsg)+1) && times-->0)
{
//SEND的非常HAPPY啊!
//num = ::recv(tcpSock,staticMsg,250,0);
//if(SOCKET_ERROR != num)
//{
// printf(staticMsg);
//}
Sleep(1000);
printf("!");
}
shutdown(tcpSock,0x02);
closesocket(tcpSock);
return 0;

}
bEst_02 2010-04-29
  • 打赏
  • 举报
回复
贴代码出来看看
dinona 2010-04-29
  • 打赏
  • 举报
回复
端口处于侦听状态,客户应该是可以connect成功的,但是send肯定不会成功的,查看send的返回值
Re:CCNA_CCNP 思科网络认证 PAT NAT 端口或地址转换 与端口映射======================# 本章课程大纲        公网地址和私网地址        NAT应用场景        静态NAT  :static  地址转换        动态NAT  :dynamic地址转换        PAT        :端口地址转换        端口映射 :port map        在Windows上同时实现的NAT和端口映射 # 私网地址三类 A类:10.0.0.0                                255.0.0.0(1网段) B类:172.16.0.0 -172.31.0.0         255.255.0.0(16网段) C类:192.168.0.0-192.168.255.0  255.255.255.0(255网段) # NAT 的使用场景        NAT的最初的目的是允许把私有IP地址映射到公网地址,以减缓IP地址空间的消耗。        当一个组织更换它的互联网服务提供商ISP,但不想更改内网配置方案时,NAT同样很有用途。        以下是适于使用NAT的多种情况:         企业内网接入Internet节省公网地址         单向访问         大方向:内网访问互联网(互联网上主机不能够访问内网主机)         小方向:同单位实现两个网段之间单向访问(涉密部门能够访问其他部门,反之不可)         增加一个网段          避免在主干路由器增加到这个网段的路由         在Windows上实现的NAT和端口映射 # 网络地址转换的类型        下面介绍一下NAT的三种类型。         静态NAT 是为了在私网地址和公网地址间,允许一对一映射而设计的。         或者IPv4和IPv6之间的转换(典型)         不节省公网地址,故公网地址的利用效率不高,         无任何安全性,外网可以通过公网地址直接攻击内网主机,好像只增加路由器的工作         适用场景类似代理,可以较方便的更换主机,而无需修改路由器的配置         故应用不够广泛...         动态NAT 可以实现映射一个未注册 IP地址到注册IP地址池中的一个注册IP地址。         多对一,或多对多         比较PAT优势:避免被误认为攻击而被封ip地址         不太节省地址,应用不广泛         复用是最流行的NAT配置类型,也被称为端口地址映射(PAT)。         通过使用PAT,可实现上千个用户仅通过一个真实的全球 IP地址连接到Internet。         缺点:增加延迟,消耗路由器性能 # 端口映射(port mapping) 允许Internet上的计算机通过企业路由器的公网IP地址访问到内网的服务器------------------------------------------------         

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧