Socket编程中创建一个单独的线程发送数据要怎么写

wuxia2118 2019-01-17 09:41:41
我想用多线程来实现将一个消息 群发给很多个客户端。因此想把send函数放在一个单独的线程里,可遇到如下问题;

1. 在线程函数中如何调用其他函数创建的Socket。

2. 在线程函数中如何访问对话框,因为要获取对话框编辑框中的内容再发送。

3. 在发送线程中是不是要用到 WaitForSingleObject 函数,我在很多这样的程序中都看到 这个函数,这个函数有什么用。

下面是我写的程序,一运行就出错。哪位好心人能给我一个做好的多线程发送数据的程序参考吗?


void CTCPServerDlg::OnSend()
{

DWORD dwThreadId = 2;

m_hSendThread = ::CreateThread(NULL, NULL, CTCPServerDlg::SendProc, ((LPVOID)this), 0, &dwThreadId);

CloseHandle(m_hSendThread);

}

DWORD WINAPI CTCPServerDlg::SendProc(LPVOID lpPar)
{
SOCKET *pClientSocket = (SOCKET*)lpPar;

CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar;

//dlg=(CTCPServerDlg*)pParam;
char buff[200];
char * ct;
CTime time = CTime::GetCurrentTime(); //获取当前时间
CString t = time.Format(" %H:%M:%S"); //设置时间显示格式
ct=(char*)t.GetBuffer(0); //cstring 转 char*
pThis->c_sendbuf.GetWindowText(buff,200);
pThis->c_sendbuf.SetWindowText(NULL);
CString Ser="服务器: >";
strcat(buff,ct);
send(*pClientSocket,buff,strlen(buff)+1,0);
pThis->c_recvbuf.AddString(Ser+buff);
return 0;
}
...全文
1306 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
叶恭介叶恭介 2019-03-21
  • 打赏
  • 举报
回复
不懂为什么要用多线程,如果需求只是很简单的话,用SOCKET事件模型就行了,不需要多线程
绿色盒子 2019-03-19
  • 打赏
  • 举报
回复
  
HANDLE hThread=CreateThread(NULL,0,WaitProc,(LPVOID)pRecvParam,0,NULL);

这个看着没啥问题啊
 
::CreateThread(NULL, NULL, CChatDlg::RecvProc, (LPVOID)sockConn, 0, &dwThreadId);
DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)
{
SOCKET *sockConn = (SOCKET*)lpParameter;
CChatDlg *pThis = (CChatDlg*)lpParameter;
//你并没有传递指针,可以随便用吗,如果传两个东西的话建议和上面等待线程一样弄个结构体
wuxia2118 2019-01-25
  • 打赏
  • 举报
回复
可能是哦,难怪我看见所有的多线程程序,发送数据都没写在一个单独的线程里,而接收数据则写在单独的线程里。可我还是不知道怎么把WaitProc线程中的套接字和窗口句柄又传递给RecvProc。
赵4老师 2019-01-24
  • 打赏
  • 举报
回复
对同一个Socket,最好只用一个线程发送数据。
否则就有可能线程1发送12345,线程2发送abcde
接收方收到12ab3c45de
Eleven 2019-01-22
  • 打赏
  • 举报
回复
你可以直接将EDIT的HWND窗口句柄传递给线程函数
wuxia2118 2019-01-22
  • 打赏
  • 举报
回复
那要怎么写代码呢,我对传参数,句柄这些东西实在不太懂
wuxia2118 2019-01-21
  • 打赏
  • 举报
回复
我现在遇到的主要问题就是不知道线程函数之间怎么传递参数,我想把线程 WaitProc中的参数sockconn和对话框句柄传给RecvProc,我下面这样写对吗,运行了一下没出错,但是接收不到任何数据。

void CChatDlg::OnCreate() //单击启动服务按钮
{
m_socket=socket(AF_INET,SOCK_STREAM,0);
if(INVALID_SOCKET==m_socket)
{
MessageBox("套接字创建失败!");
//return FALSE;
}
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_addr.S_un.S_addr=inet_addr(m_ip);
addrSock.sin_port=htons(atoi(m_port));


int retval;
retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
MessageBox("绑定失败!");
// return FALSE;
}
listen(m_socket,5);
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->sock=m_socket;
pRecvParam->hwnd=m_hWnd;
HANDLE hThread=CreateThread(NULL,0,WaitProc,(LPVOID)pRecvParam,0,NULL);
CloseHandle(hThread);
}

DWORD WINAPI CChatDlg::WaitProc(LPVOID lpParameter) //接受连接线程
{
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;


SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);
CString strNotice; /* 通知消息 */

while(1)
{
Sleep(10);

/* 创建通信套接字 */
SOCKET *sockConn = new SOCKET;
*sockConn = ::accept(sock, (SOCKADDR*)&addrFrom, &len);

if(INVALID_SOCKET == *sockConn)
{
strNotice = "accept()失败,再次尝试 ...... ";
::AfxMessageBox(strNotice);
continue;
}
else
AfxMessageBox("一个客户端已成功连接");

DWORD dwThreadId = 1;

/* 启动相应线程与客户端通信 */
::CreateThread(NULL, NULL, CChatDlg::RecvProc, (LPVOID)sockConn, 0, &dwThreadId);


}
return 0;
}


DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)
{
SOCKET *sockConn = (SOCKET*)lpParameter;
CChatDlg *pThis = (CChatDlg*)lpParameter;
// HWND hwnd=((RECVPARAM*)lpPar)->hwnd;


SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
// delete lpParameter;

SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);

char recvBuf[200];
char tempBuf[300];

while(TRUE)
{

Sleep(10);
int nRecv = ::recv(*sockConn, recvBuf, 200, 0); //接收数据
if(nRecv > 0) {
recvBuf[nRecv] = '\0'; //在接收的数据末尾处加\0
AfxMessageBox(recvBuf); //测试是否已接收到消息
}


if(SOCKET_ERROR==nRecv)
break;
sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
}
return 0;
}
void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
CString str=(char*)lParam;
CString strTemp;

c_recvbuf.AddString(strTemp);

}
woshi_hujunjun 2019-01-19
  • 打赏
  • 举报
回复
你这个有点乱,没有看到你代码中有提到过多个客户端
1. 在线程函数中如何调用其他函数创建的Socket。
可以通过参数,就像你传递this指针一样,
也可以通过全局变量

2. 在线程函数中如何访问对话框,因为要获取对话框编辑框中的内容再发送。
最好不要在线程中访问对话框。如果有交互的必要,最好通过消息来交互

3. 在发送线程中是不是要用到 WaitForSingleObject 函数,我在很多这样的程序中都看到 这个函数,这个函数有什么用。
用这个函数就相当于你接下来的操作有前置条件,WaitForSingleObject会一直等待, 直到前置条件成立或者说超时了,
或者出错了,才会往下执行,需要获取它的返回值来做判断
zgl7903 2019-01-18
  • 打赏
  • 举报
回复
再添加一个函数来方便操作

public:
DWORD SendProcFun();

DWORD CTCPServerDlg::SendProcFun()
{
//这个中的操作和普通的函数类似
}

DWORD WINAPI CTCPServerDlg::SendProc(LPVOID lpPar)
{
CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar;
__try
{
return pThis->SendProcFun();
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
{
ASSERT(0);
}
return 1;
}
wuxia2118 2019-01-17
  • 打赏
  • 举报
回复
那你说是要怎样调用外面传进来的Socket呢
zgl7903 2019-01-17
  • 打赏
  • 举报
回复
按贴出的代码  SOCKET *pClientSocket = (SOCKET*)lpPar; 很显然是不对的
运行出错 调试 结合调用堆栈修改解决之


16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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