socket非阻塞select连接问题?

__Cm_duck 2018-12-23 04:06:27
求助各位大牛, socket非阻塞select设置成3秒,如果使用一个线程去连接服务器(不阻塞UI线程),但是客户端如果一点击按钮开始连接,就立马关闭程序,此时socketEngine会被释放, socketEngine中的成员m_pITcp因为是用shared_prt所以不会被释放(?不确定), 线程中调用m_pITcp->Connect会调用系统函数connect, 并用select阻塞3秒,然后成功、超时、失败时回调给socketEngine,此时socketEngine已经被释放了,程序就触发了异常.求助怎样操作才是正常的。
bool SocketEngine::Connect(const char* ip, int port)	
{
m_strServerIp = ip;

std::thread t([this, ip, port] {
m_pITcp->Connect(ip, port, 5, 0);
});
t.detach();

return true;
}

bool XTcp::Connect(const char *ip, _word port,int second, int timeoutms)
{
if(_socket == INVALID_SOCKET) CreateSocket();

sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = inet_addr(ip);
_status = enSocketStatus_Wait;

SetBlock(false);

int ret = ::connect(_socket,(sockaddr*)&saddr,sizeof(saddr));

if (ret == 0) {
//连接成功
_status = enSocketStatus_Connect;
} else {
fd_set set;
FD_ZERO(&set);
FD_SET(_socket,&set);
timeval tm;
tm.tv_sec = second;
tm.tv_usec = timeoutms * 1000;

switch (select(_socket+1,0,&set,0,&tm)) {
case -1:
//连接失败
_status = enSocketStatus_Failture;

break;
case 0:
_status = enSocketStatus_Timeout;

break;
default:
if (FD_ISSET(_socket, &set)) {
int error = 0;
socklen_t len = sizeof(error);
#ifdef WIN32
//(win32)If no error occurs, this function returns zero. If an error occurs, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
if (getsockopt(_socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) == SOCKET_ERROR)
#else
//(linux)On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
if (getsockopt(_socket, SOL_SOCKET, SO_ERROR, &error, &len) == SOCKET_ERROR)
#endif // WIN32
{
_status = enSocketStatus_Failture;

break;
}

if (error != 0) {
//连接失败
_status = enSocketStatus_Failture;

break;
} else {
//连接成功
_status = enSocketStatus_Connect;
break;
}
}
break;
}
}

if (_pISocketEventSink)
_pISocketEventSink->OnEventTcpLink(_status);

return true;
}

...全文
581 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
__Cm_duck 2019-01-06
  • 打赏
  • 举报
回复
引用 9 楼 林多 的回复:
[quote=引用 8 楼 __Cm_duck 的回复:]
[quote=引用 3 楼 林多 的回复:]
》》》》》然后成功、超时、失败时回调给socketEngine
你指的是这个么?
if (_pISocketEventSink)
_pISocketEventSink->OnEventTcpLink(_status);

问题其实就是,异步调用导致的了。。主线程中,socketEngine被销毁。但是socket线程中,仍然去回调socketEngine了。

一种办法:再socketEngine释放(析构)时,将用来回调的对象赋值NULL。。socket线程,就不会回调socketEngine了。


socketEngine是在XTcp构造时注入,所以当socketEngine析构的时候 XTcp并不知晓[/quote]

写个回调类,不就可以知道了。在socketEngine析构里,去调这个回调类。将析构事件,通知出来。让XTcp监听,这个通知事件不就好了。[/quote]
谢谢哈 我想复杂了。
林多 2019-01-02
  • 打赏
  • 举报
回复
引用 8 楼 __Cm_duck 的回复:
[quote=引用 3 楼 林多 的回复:]
》》》》》然后成功、超时、失败时回调给socketEngine
你指的是这个么?
if (_pISocketEventSink)
_pISocketEventSink->OnEventTcpLink(_status);

问题其实就是,异步调用导致的了。。主线程中,socketEngine被销毁。但是socket线程中,仍然去回调socketEngine了。

一种办法:再socketEngine释放(析构)时,将用来回调的对象赋值NULL。。socket线程,就不会回调socketEngine了。


socketEngine是在XTcp构造时注入,所以当socketEngine析构的时候 XTcp并不知晓[/quote]

写个回调类,不就可以知道了。在socketEngine析构里,去调这个回调类。将析构事件,通知出来。让XTcp监听,这个通知事件不就好了。
__Cm_duck 2018-12-30
  • 打赏
  • 举报
回复
引用 3 楼 林多 的回复:
》》》》》然后成功、超时、失败时回调给socketEngine
你指的是这个么?
if (_pISocketEventSink)
_pISocketEventSink->OnEventTcpLink(_status);

问题其实就是,异步调用导致的了。。主线程中,socketEngine被销毁。但是socket线程中,仍然去回调socketEngine了。

一种办法:再socketEngine释放(析构)时,将用来回调的对象赋值NULL。。socket线程,就不会回调socketEngine了。


socketEngine是在XTcp构造时注入,所以当socketEngine析构的时候 XTcp并不知晓
__Cm_duck 2018-12-30
  • 打赏
  • 举报
回复
引用 6 楼 way2home 的回复:
没看到问题描述;不想让SocketEngine销毁可以让把SocketEngine的shared_from_this()传给线程,在想释放的时候释放。
建议使用别人写好的跨平台网络库

你是指SocketEngine继承enable_shared_from_this吗?这个有想过 但是不知道怎么传shared_from_this()给线程的匿名函数,可以示例下代码么 谢谢
赵4老师 2018-12-27
  • 打赏
  • 举报
回复
引用 4 楼 轻箬笠 的回复:
[quote=引用 2 楼 赵4老师 的回复:]
MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix, MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

赵老师是不是接近csdn的内部人员啊?能不能反应下,用360安全浏览器打开,代码部分会有很多“<br data-filtered="filtered">”?chrome是没有的。[/quote]
就我还“接近csdn的内部人员”呢?!
都快被csdn拉黑了都!!!!https://bbs.csdn.net/topics/392401138

way2home 2018-12-27
  • 打赏
  • 举报
回复
没看到问题描述;不想让SocketEngine销毁可以让把SocketEngine的shared_from_this()传给线程,在想释放的时候释放。 建议使用别人写好的跨平台网络库
轻箬笠 2018-12-26
  • 打赏
  • 举报
回复
引用 2 楼 赵4老师 的回复:
MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix, MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

赵老师是不是接近csdn的内部人员啊?能不能反应下,用360安全浏览器打开,代码部分会有很多“<br data-filtered="filtered">”?chrome是没有的。
林多 2018-12-26
  • 打赏
  • 举报
回复
》》》》》然后成功、超时、失败时回调给socketEngine
你指的是这个么?
if (_pISocketEventSink)
_pISocketEventSink->OnEventTcpLink(_status);

问题其实就是,异步调用导致的了。。主线程中,socketEngine被销毁。但是socket线程中,仍然去回调socketEngine了。

一种办法:再socketEngine释放(析构)时,将用来回调的对象赋值NULL。。socket线程,就不会回调socketEngine了。
赵4老师 2018-12-24
  • 打赏
  • 举报
回复
smwhotjay 2018-12-23
  • 打赏
  • 举报
回复

搞懂tcp 再封装

64,674

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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