关于异步socket的回调
急啊
遇到了一个问题,
MFC中异步socket,调用connect函数,有时(是偶尔)connect成功之后(server端已经打印出了request的tcp address,证明已经connected),此异步socket不回调OnConnect函数,
之前的调用Connect()后lastError==10035,说明是异步调用方式
急啊!!!!!!!!!!!!!!
问题点数:135、回复次数:33Top
1 楼ShyWJB(家宝)回复于 2001-11-13 03:16:05 得分 0
我也正在做这样一个程序,可惜我才开始学,关注Top
2 楼sizhi(人在江湖飘啊~,哪能不挨刀啊~~)回复于 2001-11-13 08:27:14 得分 0
唉..无能为力,关注!!Top
3 楼evelan(醉猫)回复于 2001-11-13 08:36:53 得分 135
不能根据connect函数的返回值判断,重载OnConnect 在OnConnect中判断nError的值可得知成功是否Top
4 楼borz(中五百万或是更多)回复于 2001-11-13 08:46:21 得分 0
to醉猫:是啊我得一connect的反回值为WSAEWOULDBLOCK,这说明这是一个异步的操作,而我早已重载了OnConnect函数,但有时(我是说有时)系统却不回调这个onconnectTop
5 楼liuyinfeng(向你飞翔)回复于 2001-11-13 09:41:22 得分 0
hi
不知道您使用的是不是CSocket类,对于OnConnect在CSocket类里有点说法,别的就应该没什么了。能说的详细点吗?Top
6 楼DeadWolf(三角小眼睛又邪又媚又笨又呆又奸又诈又色)回复于 2001-11-13 09:43:46 得分 0
如果网络有问题 或者connect 的IP地址不正确的话
OnConnect 可能会等待一个比较长的时间 超时以后才会来
Top
7 楼zx_sanjin(www.chmbook.com - CHM电子书网)回复于 2001-11-13 09:52:33 得分 0
还是用SDK吧, 代码量都差不多的~~~Top
8 楼xtky_limi(窗外细雨)回复于 2001-11-13 10:04:02 得分 0
无能为力,关注!! Top
9 楼supperapplication(行星)回复于 2001-11-13 10:31:37 得分 0
在后面加上这个试试:CAysncSocket::AsyncSelect(FD_CONNECT );Top
10 楼zj_ok(zj_ok)回复于 2001-11-13 11:03:47 得分 0
有一个问题OnConnect是在accept之前还是之后调用?Top
11 楼eggplant(拉拉)回复于 2001-11-13 11:19:30 得分 0
关键是你的客户端Socket有没有机会处理FD_CONNECT事件?你的程序是不是进入了死循环而不能响应这个事件?Top
12 楼superdreamer(只懂一点点!)回复于 2001-11-13 11:26:12 得分 0
把你的代码贴出来,大家一起讨论Top
13 楼borz(中五百万或是更多)回复于 2001-11-13 11:57:23 得分 0
我把情况给大家说说
我后来跟踪到里面去了,
发现实际上connect成功时CAsyncSocket::DoCallBack(。。。)
他走的是case FD_READ:即read buffer有用,而不是FD_CONNECT
我的处理流程是这样的:
1:connect, 2:send ,3:receive 第3步如果出错了或是结果不对,服务器就会关闭当前
socket,同时还会向客户端返回错误号,而我在客户端会根据返回的错误号,决定是否重新连接,然后再发送相应的请求,现在就是在重发请求之前的连接出了这个问题
下面是我连接的部分代码
m_Socket是类中的成员变量
m_Socket.Close();
if(m_Socket.Open(bp3_App->m_SrvAddr,bp3_App->m_SrvPort,error))
return TRUE;
else
{
....
}
下面是socket的代码
BOOL CBPSocket::Open(CString host,unsigned short port,CString& msg)
{
BOOL ok = FALSE;
HOSTENT *lpHost;
SOCKADDR_IN sockaddr_in;
//SetSockOpt(IPPROTO_TCP,&bp3_NetworkTimeout,sizeof(UINT),SO_RCVTIMEO);
lpHost = gethostbyname(host);
if(lpHost!=NULL)
{
if(!Create())
msg.Format("Create Socket object error, error code:%d",GetLastError());
else
{
sockaddr_in.sin_family = AF_INET;
sockaddr_in.sin_port = htons(port);
sockaddr_in.sin_addr.s_addr=((LPIN_ADDR)lpHost->h_addr)->s_addr;
AsyncSelect(FD_READ | FD_CLOSE | FD_CONNECT);
UINT r = Connect((SOCKADDR*)(&sockaddr_in),sizeof(SOCKADDR));
DWORD lastError = GetLastError();
#ifdef BP3_SOCKET_LOGFILE
CString str1;
str1.Format("\r\nCall Connect(), lastError:%d",lastError);
m_logFile.Write(str1,str1.GetLength());
#endif
if(!r && lastError==WSAEWOULDBLOCK)
ok = TRUE;
else
msg.Format("Failed to connect with server:'%s',error code:%d",host,GetLastError());
}
}
else
msg.Format("Couldn't resolve host name '%s'",host);
return ok;
}
void CBPSocket::OnConnect(int nErrorCode)
{
#ifdef BP3_SOCKET_LOGFILE
CString str1;
str1.Format("\r\nOnConnect(), nErrorCode:%d",nErrorCode);
m_logFile.Write(str1,str1.GetLength());
#endif
bp3_App->GetDefDoc()->OnConnect(nErrorCode);
CAsyncSocket::OnReceive(nErrorCode);
}Top
14 楼liuyinfeng(向你飞翔)回复于 2001-11-13 12:40:54 得分 0
您能否将if(!Create())改为(!Create(0,SOCK_STREAM,FD_READ ¦ FD_CLOSE ¦ FD_CONNECT));然后connect的地方就可以Connect("IP","端口").
这样试一下?Top
15 楼borz(中五百万或是更多)回复于 2001-11-13 12:57:05 得分 0
为什么要这样呢
BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddress = NULL );
其缺省的不就是可用的吗?
Top
16 楼liuyinfeng(向你飞翔)回复于 2001-11-13 13:47:58 得分 0
hi,
是的,说句心里话你的代码我还没看出什么问题,上一个问题只不过换一种我认为比较保险的方式。
再次问一下,是不是你再次open的时候,onconnect的代码没有执行?
关于LPIN_ADDR稍有疑问,可否改成inet_addr(写死的地址),然后后面的能注则注,试验一下?Top
17 楼liuyinfeng(向你飞翔)回复于 2001-11-13 13:59:57 得分 0
还有,能不能先Create,然后在open一下,m_Socket在open函数中自己调用create,就是自己创建自己是否可行?虽然感觉应该可以,但还是保险一下。Top
18 楼borz(中五百万或是更多)回复于 2001-11-13 15:11:03 得分 0
是的,再次open时onconnect不回调,就是这个毛病Top
19 楼supperapplication(行星)回复于 2001-11-14 09:58:32 得分 0
你可以在CAsyncSocket::receive()或者send()之后,加上CAysncSocket::AsyncSelect(FD_CONNECT ); 我原来也有类似的错误,就是这样解决的。Top
20 楼borz(中五百万或是更多)回复于 2001-11-14 21:18:36 得分 0
我这样试过了,可在win98 中文下,会造成onconnect的多次响应,2000下不会Top
21 楼borz(中五百万或是更多)回复于 2001-11-14 21:26:41 得分 0
现在我通过改用指针访问搞掂了,即每次
m_pSocket = new ....
m_pSocket->...
用完后
m_pSocket->Close();
delete m_pSocket;
m_pSocket = NULL;
用一个同行的话说,"感觉这样放心一些"
虽然这样,但我还是不能确定最根本的原因,请大家继续帮助Top
22 楼supperapplication(行星)回复于 2001-11-14 21:59:11 得分 0
我不知道win98下会怎么样?我这里没有98。Top
23 楼supperapplication(行星)回复于 2001-11-14 22:01:37 得分 0
把这句话去掉AsyncSelect(FD_READ ¦ FD_CLOSE ¦ FD_CONNECT);
放在recv之后。
Top
24 楼borz(中五百万或是更多)回复于 2001-11-14 22:58:13 得分 0
为什么呢?Top
25 楼amoroso(鼠标)回复于 2001-11-14 23:29:07 得分 0
学习Top
26 楼iconlee()回复于 2001-11-15 02:45:40 得分 0
学习Top
27 楼kenthuang()回复于 2001-11-16 12:49:40 得分 0
socket连接在close()之后不一定就立即关闭。如果close()之后立即调用open(),有可能还是以同一socket与对端连接,此时自然也不会有OnConnect事件发生。Top
28 楼walk21cn()回复于 2001-11-16 13:00:28 得分 0
建议使用winsock event 写,不要用mfc的类,不灵活Top
29 楼borz(中五百万或是更多)回复于 2001-11-17 11:14:15 得分 0
kenthuang似乎说到点子上了,但我还有一个疑问,后来我在close之前将他设为
阻塞工作方式,然后再close,难道这也不能保证close完全吗? 在这种情况下偶尔也会上现上
面的错误Top
30 楼sunyee(sunyee)回复于 2001-11-18 13:00:45 得分 0
我在上面的贴子中看到:
现在我通过改用指针访问搞掂了,即每次
m_pSocket = new ....
m_pSocket->...
用完后
m_pSocket->Close();
delete m_pSocket;
m_pSocket = NULL;
你这样做的用意可能是:在Close一个SOCKET后接着又想用它。(?)
如果是这样的话,可以这样做:
用的时候:
m_pSocket->Create();
m_pSocket->Connect(,);
.....
用完后:
m_pSocket->Close();
在OnClose()中:
Detach();
以后要再用的话,只要调上面的“用的时候”的代码即可,而无需new->delete->new->...
这是我的看法。Top
31 楼elic(michael)回复于 2001-11-18 21:57:38 得分 0
用CAsyncSocketTop
32 楼borz(中五百万或是更多)回复于 2001-11-21 11:26:14 得分 0
to:sunyee
我的确是想在close后继续使用,但现实是close后我必须马上调用create,然后connect来创建新的连接。
我怀疑这样会造成socket回调的的混乱(因为在调用create之前onclose回调还根本没有产生),我看内裤里面的回调入口代码他是基于一个集合类来实现管理两种链表的,一个用来装所有已经death的,另一个装正在工作的。 出于这个担心,我后来就干脆用new操作来产生新的地址,那是无论无何不会出现冲突了。
欢迎继续探讨:)
Top
33 楼javanew(我是java新手)回复于 2002-08-04 15:37:51 得分 0
222333Top




