我想写一个 TCP 一对多通信的程序,就是服务器端利用多线程技术(不使用Select等任何模型), 服务器端能将消息群发给所有已连接的客户端, 我参考了其他一些程序,发现基本思路 是将每个线程中 accept函数返回的套接字 都保存到一个套接字数组中,套接字地址也保存到一个数组中。然后在“群发”的 按钮消息中,用for循环 遍历套接字数组,循环执行 send函数将消息发送给套接字数组中所有的套接字。 可我用send()函数发送就产生SOCKET_ERROR错误,输出错误代码是10038,无效的套接字,说明套接字根本没保存到套接字数组中去,用list结构保存套接字也是这样,不行,请问这是为什么,我的关键代码如下:。
BOOL CListWinDlg::OnInitDialog()
{
CDialog::OnInitDialog(); SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
WSADATA wsaData;
WORD sockVersion=MAKEWORD(2,2);
sockSer=socket(AF_INET,SOCK_STREAM,0);
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
addrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
int len =sizeof(SOCKADDR);
bind(sockSer,(SOCKADDR*) &addrSer,len);
listen(sockSer,5);
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->sock=sockSer;
pRecvParam->hwnd=m_hWnd;
HANDLE hThread=CreateThread(NULL,0,WaitProc,(LPVOID)pRecvParam,0,NULL);
CloseHandle(hThread);
return 0;
}
DWORD WINAPI CListWinDlg::WaitProc(LPVOID lpParameter) //接受连接线程
{
CListWinDlg *pServer=new CListWinDlg;
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
SOCKET sockConn;
SOCKADDR_IN addrCli;
int len =sizeof(SOCKADDR);
int num=0;
while(1)
{
Sleep(10); //这句有什么用?
sockConn=accept(sock,(SOCKADDR*) &addrCli,&len);
if(INVALID_SOCKET == sockConn)
{
CString strNotice = "accept()失败,再次尝试 ...... ";
::AfxMessageBox(strNotice);
continue;
}
else{ AfxMessageBox("一个客户端已成功连接");
// pServer->m_listConn.push_back(addrCli);
// pServer->m_sockConn.push_back(sockConn);
pServer->m_Clients[num]=sockConn; //将套接字保存到数组中,
pServer->addrFrom[num]=addrCli;
num++;
} //将套接字地址保存到数组中
// int num2=sizeof(pServer->m_Clients)/sizeof(pServer->m_Clients[0]);
} return TRUE;
}
void CListWinDlg::OnSend()
{
char buff[200];
char * ct;
CTime time = CTime::GetCurrentTime(); //获取当前时间
CString t = time.Format(" %H:%M:%S"); //设置时间显示格式
ct=(char*)t.GetBuffer(0); //cstring 转 char*
c_sendbuf.GetWindowText(buff,200);
c_sendbuf.SetWindowText(NULL);
CString Ser="服务器: >";
strcat(buff,ct);
int iSendFalseCount=0;
CListWinDlg *pServer=new CListWinDlg;
// for (sockiterator = m_sockConn.begin(); sockiterator != m_sockConn.end(); ++sockiterator)
// for (list<SOCKET>::iterator itr=pServer->m_sockConn.begin();itr!=pServer->m_sockConn.end();itr++)
for(int i=0;i<3;i++)
{
int vetcal=send(pServer->m_Clients[i],buff,strlen(buff)+1,0);
if (vetcal==SOCKET_ERROR)
iSendFalseCount++;
}
iSendFalseCount=WSAGetLastError();
char strtemp[5];
itoa(iSendFalseCount, strtemp, 10);
AfxMessageBox(strtemp);
}
头文件中定义的数组如下:
struct RECVPARAM
{
SOCKET sock;
HWND hwnd;
};
class CListWinDlg : public CDialog
{
// Construction
public:
CListWinDlg(CWnd* pParent = NULL); // standard constructor SOCKET sockSer,sockConn;
SOCKET m_Clients[10]; //保存套接字的数组
SOCKADDR_IN addrFrom[10]; list<SOCKET> m_sockConn;
list<SOCKADDR_IN> m_listConn;
list<SOCKET>::iterator sockiterator;
SOCKADDR_IN addrSer;
list<string> test;list<string>::iterator testiterator;
static DWORD WINAPI WaitProc(LPVOID lpParameter);
static DWORD WINAPI RecvProc(LPVOID lpParameter);
解决方案 »
- --------->>为什么这样不出错啊??
- 一个局域网聊天小程序的小问题
- 能够声明一个可变大小的结构数组吗?
- MDI窗口中 怎样才能建立一个子窗口
- 数据库程序写完后怎么才能让它在别的机器上运行?
- 我想把帖子结了,可是有些问题没有人回答,或者不值得给分,我怎么结贴啊?
- 请问:如何将 北大方正 的文件输出成 PostScript(*.ps) 文件
- 大家开发MFC应用一般用什么性能工具测试性能?
- 我是菜鸟,谁能告诉我:DLL和OBJ有什么本质区别?DLL到底有什么比OBJ强大的多的地方?
- 请给我介绍一下onidle虚函数的使用方法,给个例子。
- 关于UNICODE_STRING
- Teechart 3D绘图时, 找不到成员函数
CListWinDlg *pServer=new CListWinDlg;所以你保存和使用的不是同一个对象实例,这两个对象的数据是不共享的
你应该使用同一个,或者使用静态数组
是一个 与 原 对话框 无关的 新对象 !WaitProc(LPVOID lpParameter)// 传 对话框 窗口 对话框 定义
RECVPARAM RecvParam;或者
RECVPARAM *pRecvParam=new RECVPARAM;
放 类外
//*******本来在chatDlg.h中定义的,现在移到这里,为解决连接时重复定义问题
SOCKET * m_Clients[10]; //保存套接字的数组
SOCKADDR_IN addrCli[10];
int num;
//****************************************************
https://download.csdn.net/download/wuxia2118/10946379