如何完全停止正在监听的Socket

snowfog 2004-03-19 10:00:47
我的程序中有一个监听Socket,它对应一个监听线程,该线程中使用事件选择的方式监听FD_ACCEPT和FD_CLOSE;在外部的主线程中希望关闭该监听线程,使用closesocket不成功,因为waitfor函数不返回,不知道该如何做?
...全文
689 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
itren 2004-03-19
  • 打赏
  • 举报
回复
呵呵!
snowfog 2004-03-19
  • 打赏
  • 举报
回复
侦听的套接字如何在服务器端主动产生 FD_CLOSE 事件?这个问题还没有解决。
xstring 2004-03-19
  • 打赏
  • 举报
回复
肯定是端口还被占用着,所以bind不成功

不知道你重新启动服务时, StopServ是不是被调用了

查查看

snowfog 2004-03-19
  • 打赏
  • 举报
回复
我是一个指针用错了,改正之后就不会有上面的问题了。
感谢大家!
过会就结帖。
snowfog 2004-03-19
  • 打赏
  • 举报
回复
我使用为主线程增加事件的方式之后可以停止监听线程的运行。但是再次重新启动服务器时第一次调用StartServ失败,第二次就成功,错误是发生在bind函数。为什么?怎么解决?
int CSocketServer::StartServ()
{
if (m_ServiceState == SS_Started)
{
return SUCCESS;
}

sockaddr_in local;//本地服务器地址
HANDLE hThread;//监听线程句柄
DWORD dwThreadId;//监听线程Id

//创建监听Socket
m_sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (m_sListen == SOCKET_ERROR)
{
m_iInitSuccess = FAULT;
closesocket(m_sListen);
return m_iInitSuccess;
}

//绑定
local.sin_addr.s_addr = inet_addr(m_cServerIP);
local.sin_family = AF_INET;
local.sin_port = htons(m_iServerPort);
if (bind(m_sListen, (sockaddr *)&local, sizeof(local)) == SOCKET_ERROR)
{
m_iInitSuccess = FAULT;
closesocket(m_sListen);
return m_iInitSuccess;
}

//监听
listen(m_sListen, m_iBacklog);

。。。
}

int CSocketServer::StopServ()
{
SetEvent(m_MainEvent);
shutdown(m_sListen, SD_BOTH);
closesocket(m_sListen);
}

comman_wang 2004-03-19
  • 打赏
  • 举报
回复
先调用shutdown(),再调用closesocket()。
因为closesocket只是使引用减1,当为零时,才关闭。
snowfog 2004-03-19
  • 打赏
  • 举报
回复
我在服务器端为每个客户端建立的socket及线程,服务器就是主动调用closesocket就能够触发FD_CLOSE事件。
flinming 2004-03-19
  • 打赏
  • 举报
回复
线程先关闭再说。。。
chenwhenlong 2004-03-19
  • 打赏
  • 举报
回复
要是会发生 FD_CLOSE 事件,假设有 5 个client 进行连接,那不就要发生 5 个 FD_CLOSE 事件吗?
chenwhenlong 2004-03-19
  • 打赏
  • 举报
回复
侦听的套接字不会产生 FD_CLOSE 事件。
FD_CLOSE 事件是要对方断开连接时才会发生的。

要是会发生 FD_CLOSE 事件,假设有 5 个client 进行连接,那不就要发生 FD_CLOSE 事件吗?
snowfog 2004-03-19
  • 打赏
  • 举报
回复
我就是调用了closesocket而没有触发close事件。
chenwhenlong 2004-03-19
  • 打赏
  • 举报
回复
FD_CLOSE 事件是对方调用 closesocket 时才会触发吧?
snowfog 2004-03-19
  • 打赏
  • 举报
回复
xstring(麻雀) ,chenwhenlong(bester) 的方法是相同的,而且应该可行,我再试试。
不过有没有办法使监听socket触发close的事件?相应的为每个客户端建立的线程是可以用closesocket触发close事件的。
chenwhenlong 2004-03-19
  • 打赏
  • 举报
回复

我暂时是这样实现的:

UINT WINAPI ListenThreadProc(LPDWORD pvData)
{
WSAEVENT wsaEvents[2];
SOCKET hSocket = (SOCKET)pvData[0];
wsaEvents[0] = (WSAEVENT)pvData[1]; // 主线程要求关闭时通知的事件对象
wsaEvents[1] = (WSAEVENT)pvData[2]; // 有网络事件时通知的事件对象

/////////////////////////////////////////////////////////////////////
// 等待并处理客户事件
DWORD dwWaitStatus;
BOOL bExitThread = FALSE;
WSANETWORKEVENTS NetworkEvents;
while (!bExitThread) {
// 等待客户加入或停止 IOCPServer...
dwWaitStatus = WSAWaitForMultipleEvents(2, wsaEvents, FALSE,
INFINITE, FALSE);

switch(dwWaitStatus) {
case WSA_WAIT_EVENT_0: // 主线程要求关闭
bExitThread = TRUE; // 退出线程
break;

case WSA_WAIT_EVENT_0 + 1: // 网络事件
if (WSAEnumNetworkEvents(hSocket, wsaEvents[1], &NetworkEvents)
!= SOCKET_ERROR)
{
// 处理网络事件
}
break;

default:
break;
}
}
closesocket(hSocket);
WSACloseEvent(wsaEvents[0]);
WSACloseEvent(wsaEvents[1]);
return 0;
}
xstring 2004-03-19
  • 打赏
  • 举报
回复
主线程中多创建一个event

在监听线程中使用WaitForMultipleObject,传入跟socket有关的那个event和主线程中创建的那个event,不要wait all

要停止监听时,在主线程中调用SetEvent (主线程创建的那个event)

这样监听线程中WaitFor会返回,监听线程这时候closesocket就可以了
mzg3 2004-03-19
  • 打赏
  • 举报
回复
listen的是不会产生FD_CLOSE事件的
如果你硬是要这个事件的话就自己产生好了:
if (closesocket(listenfd)!=SOCKET_ERROR)
SendMessage(WM_XXXX,listenfd,FD_CLOSE);

其中:
listenfd是侦听的套接字
WM_XXXX是你自己定义的SOCKET关闭的事件
本PDF电子书包含上下两册,共1576页,带目录,高清非扫描版本。 作者: 毛德操 胡希明 丛书名: Linux内核源代码情景分析 出版社:浙江大学出版社 目录 第1章 预备知识 1.1 Linux内核简介. 1.2 Intel X86 CPU系列的寻址方式 1.3 i386的页式内存管理机制 1.4 Linux内核源代码中的C语言代码 1.5 Linux内核源代码中的汇编语言代码 第2章 存储管理 2.1 Linux内存管理的基本框架 2.2 地址映射的全过程 2.3 几个重要的数据结构和函数 2.4 越界访问 2.5 用户堆栈的扩展 2.6 物理页面的使用和周转 2.7 物理页面的分配 2.8 页面的定期换出 2.9 页面的换入 2.10 内核缓冲区的管理 2.11 外部设备存储空间的地址映射 2.12 系统调用brk() 2.13 系统调用mmap() 第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3.2 中断向量表IDT的初始化 3.3 中断请求队列的初始化 3.4 中断的响应和服务 3.5 软中断与Bottom Half 3.6 页面异常的进入和返回 3.7 时钟中断 3.8 系统调用 3.9 系统调用号与跳转表 第4章 进程与进程调度 4.1 进程四要素 4.2 进程三部曲:创建、执行与消亡 4.3 系统调用fork()、vfork()与clone() 4.4 系统调用execve() 4.5 系统调用exit()与wait4() 4.6 进程的调度与切换 4.7 强制性调度 4.8 系统调用nanosleep()和pause() 4.9 内核中的互斥操作 第5章 文件系统 5.1 概述 5.2 从路径名到目标节点 5.3 访问权限与文件安全性 5.4 文件系统的安装和拆卸 5.5 文件的打开与关闭 5.6 文件的写与读 5.7 其他文件操作 5.8 特殊文件系统/proc 第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用socket() 7.2函数sys—socket()——创建插口 7.3函数sys—bind()——指定插口地址 7.4函数sys—listen()——设定server插口 7.5函数sys—accept()——接受连接请求 7.6函数sys—connect()——请求连接 7.7报文的接收与发送 7.8插口的关闭 7.9其他 第8章设备驱动 8.1概述 8.2系统调用mknod() 8.3可安装模块 8.4PCI总线 8.5块设备的驱动 8.6字符设备驱动概述 8.7终端设备与汉字信息处理 8.8控制台的驱动 8.9通用串行外部总线USB 8.10系统调用select()以及异步输入/输出 8.11设备文件系统devfs 第9章多处理器SMP系统结构 9.1概述 9.2SMP结构中的互斥问题 9.3高速缓存与内存的一致性 9.4SMP结构中的中断机制 9.5SMP结构中的进程调度 9.6SMP系统的引导 第10章系统引导和初始化 10.1系统引导过程概述 10.2系统初始化(第一阶段) 10.3系统初始化(第二阶段) 10.4系统初始化(第三阶段) 10.5系统的关闭和重引导

18,363

社区成员

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

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