socket多线程问题

Rocky_ 2008-10-25 06:42:16
新学socket 写一个聊天室程序
思路如下:
由服务创建监听socket
并创建一个新的线程
线程中 accept 连接
每accept一个连接创建一个新线程与之通信
请不要分析性能之类 请问为什么没法在子线程中运行while循环呢 MFC Dialog base program
部分代码如下:

//服务器端创建accept线程
DWORD WINAPI CSocketDlg::clientthreadproc(LPVOID lpParameter)
{
SOCKET s;
SOCKADDR_IN skt_addr;
int len=sizeof(sockaddr);
s=accept(((threaddata*)lpParameter)->skt,(sockaddr*)&skt_addr,&len);
while(TRUE)
{
if(s!=INVALID_SOCKET)
{
HANDLE tempthreadhandle;
threaddata* trdd1=new threaddata;
trdd1->hwnd=((threaddata*)lpParameter)->hwnd;
trdd1->skt=s;
trdd1->addr=skt_addr;
CreateThread(NULL,0,chatproc,LPVOID(trdd1),0,NULL);
CloseHandle(tempthreadhandle);
}
}
delete (threaddata*)lpParameter;
return 0;
}
...全文
188 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
qmj150 2011-11-22
  • 打赏
  • 举报
回复
学习了~
Rocky_ 2008-10-25
  • 打赏
  • 举报
回复
是创建线程返回的句柄 少写了一句 呵呵
确实是初写网络方面的程序 有很多问题

cnzdgs 2008-10-25
  • 打赏
  • 举报
回复
跳出线程是什么意思?如果是异常终止,在accept上设置断点,查看一下lpParameter和skt的值是不是有问题。
cppwin 2008-10-25
  • 打赏
  • 举报
回复
我的程序运行到 s=accept(((threaddata*)lpParameter)->skt,(sockaddr*)&skt_addr,&len);
这一行就跳出线程弹出程序主窗口 单步执行也不会运行这一句后面的线程代码

原因是 accept阻塞了线程.

请问可以做到一直listen accept一个就新建一个线程吗
将accept放到while循环里面.


总之,代码问题比较多,比如tempthreadhandle从来没有赋值,就被close.
多做练习吧
Rocky_ 2008-10-25
  • 打赏
  • 举报
回复
是线程里没有事件对象吗
我发现在程序关闭后才会运行accept下一句中的while循环
Rocky_ 2008-10-25
  • 打赏
  • 举报
回复
我的项目名称是Socket 基于对话框的简易聊天程序
所以类名为CSocketDlg
程序流程如下
CSocketDlg::OnInitDialog()函数里运行InitSocket()函数
InitSocket()函数初始化套接字库 并且创建套接字 绑定 监听
接着OnInitDialog()函数创建线程
线程函数DWORD WINAPI CSocketDlg::clientthreadproc(LPVOID lpParameter)
accept连接 并再次创建新线程用来通信
Rocky_ 2008-10-25
  • 打赏
  • 举报
回复
具体是这样的
m_skt是CSocketDialog一个SOCKET成员
成员初始化的时候用它来接受socket()返回的socket对象
然后bind listen...
初始化函数如下:

//m_skt是CSocketDlg的SOCKET成员
BOOL CSocketDlg::InitSocket(void)
{//协议版本
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
AfxMessageBox(_T("Can not find WinSocket Dll!"));
return FALSE;
}

if ( LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2 ) {
AfxMessageBox(_T("Can not find a useful WinSocket Dll!"));
WSACleanup( );
return FALSE;
}
//创建套接字
m_skt=socket(AF_INET,SOCK_STREAM ,IPPROTO_TCP);
if(INVALID_SOCKET==m_skt)
{
AfxMessageBox(_T("Socket Create failed"));
return FALSE;
}
sockaddr_in sktsrvaddr;
sktsrvaddr.sin_family=AF_INET;
sktsrvaddr.sin_port=htons(m_uPort);
sktsrvaddr.sin_addr.S_un.S_addr=inet_addr("192.168.0.252");
//bind
if(SOCKET_ERROR==bind(m_skt,(sockaddr*)&sktsrvaddr,sizeof(sockaddr)))
{
closesocket(m_skt);
AfxMessageBox(_T("Bind failed"));
return FALSE;
}
//listen
if(SOCKET_ERROR==listen(m_skt,SOMAXCONN))
{
closesocket(m_skt);
AfxMessageBox(_T("Listen failed"));
return FALSE;
}
return TRUE;
}

然后在OnInitDialog函数中调用InitSocket()函数
部分代码如下:

struct threaddata //自定义结构体用来给线程函数传值
{
HWND hwnd;
SOCKET skt;
SOCKADDR_IN addr;
};
BOOL CSocketDlg::OnInitDialog()
{
//..... 略去MFC代码
if(InitSocket())//判断套接字是否创建绑定并监听
{
m_strReceive+=_T("\r\nTCP Socket Initialize successful!");
SetDlgItemText(IDC_RECEIVE,m_strReceive);
}
threaddata* trdd=new threaddata; //new一个自定义的结构体并赋值
trdd->hwnd=m_hWnd;
trdd->skt=m_skt;
//创建线程 我打算在新创建的线程里accept 如果accept到连接 就在此线程中再创建线程来通信
HANDLE clientthread=CreateThread(NULL,0,clientthreadproc,LPVOID(trdd),0,NULL);
CloseHandle(clientthread);
return TRUE;
}

accept线程函数 这个函数出现顶楼说明的问题

DWORD WINAPI CSocketDlg::clientthreadproc(LPVOID lpParameter)
{
SOCKET s=INVALID_SOCKET; //初始化一个套接字变量为失败值
SOCKADDR_IN skt_addr;
int len=sizeof(sockaddr);
s=accept(((threaddata*)lpParameter)->skt,(sockaddr*)&skt_addr,&len); //监听... 这里出错 程序运行到这直接跳出线程函数 不运行下面的代码
while(TRUE)
{if(s!=INVALID_SOCKET)
{
HANDLE tempthreadhandle;
threaddata* trdd1=new threaddata; //new 结构体
trdd1->hwnd=((threaddata*)lpParameter)->hwnd;
trdd1->skt=s;
trdd1->addr=skt_addr;
CreateThread(NULL,0,chatproc,LPVOID(trdd1),0,NULL); //创建线程用来通信
CloseHandle(tempthreadhandle);
}
}
delete (threaddata*)lpParameter;
return 0;
}

程序无论是单步调试还是设置断点 都在accept函数那里直接跳出线程函数了
请问代码有什么逻辑错误吗? 界面可以正常运行 但没有功能
恳请懂TCP网络编程的朋友指点迷津
这是我学习TCP套接字编程的一道坎 解决问题后另加分相赠 再次感谢!
cnzdgs 2008-10-25
  • 打赏
  • 举报
回复
m_skt是从哪来的?还有,创建线程之后执行什么操作?
通常的做法应该是在一个线程中循环accept,每次accept成功后创建一个线程来处理此连接。
Rocky_ 2008-10-25
  • 打赏
  • 举报
回复
请问可以做到一直listen accept一个就新建一个线程吗
我的程序运行到 s=accept(((threaddata*)lpParameter)->skt,(sockaddr*)&skt_addr,&len);
这一行就跳出线程弹出程序主窗口 单步执行也不会运行这一句后面的线程代码
如楼上所示改过也一样
事实上这时客户端没有发出连接请求
理论上它应该是处于监听状态
是不是线程不在运行状态会导致accept立即返回呢?
dirdirdir3 2008-10-25
  • 打赏
  • 举报
回复
你的这个while怎么退出,而且s被accept了以后会一直开进程,因为在while里面根本没有为s符值...............
应该在去掉while里面
SOCKET s;
SOCKADDR_IN skt_addr;
int len=sizeof(sockaddr);
s=accept(((threaddata*)lpParameter)->skt,(sockaddr*)&skt_addr,&len);
if(s!=INVALID_SOCKET)
{
HANDLE tempthreadhandle;
threaddata* trdd1=new threaddata;
trdd1->hwnd=((threaddata*)lpParameter)->hwnd;
trdd1->skt=s;
trdd1->addr=skt_addr;
CreateThread(NULL,0,chatproc,LPVOID(trdd1),0,NULL);
CloseHandle(tempthreadhandle);
}
delete (threaddata*)lpParameter;
return 0;

需要多接收几个就需要多listen几次..........
Rocky_ 2008-10-25
  • 打赏
  • 举报
回复
上面贴的函数是主程序中新创建的线程的线程函数:
主函数部分代码如下:

if(InitSocket())
{
m_strReceive+=_T("\r\nTCP Socket Initialize successful!");
SetDlgItemText(IDC_RECEIVE,m_strReceive);
}
threaddata* trdd=new threaddata;
trdd->hwnd=m_hWnd;
trdd->skt=m_skt;
HANDLE clientthread=CreateThread(NULL,0,clientthreadproc,LPVOID(trdd),0,NULL);
CloseHandle(clientthread);


请问为什么程序执行到线程函数的

s=accept(((threaddata*)lpParameter)->skt,(sockaddr*)&skt_addr,&len);

这一句就跳出线程了呢
且不进入线程函数的while循环

15,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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