void CMFC_SocketServerDlg::OnBnClickedBtnstart()
{
if (connected || listening)//若正在监听或已连接则关闭服务器
{
connected = false;
listening = false;
closesocket(toClient);
closesocket(Listener);
m_chat += "Socket Server Stopped!\r\n";
UpdateData(false);//拷贝变量值到控件显示。(变量的最终运算结果值交给外部输出显示)
return;
}
UpdateData(true);//刷新控件的值到对应的变量。(外部输入值交给内部变量)
//创建监听Socket
struct protoent *ppe;
ppe = getprotobyname("tcp");
if ((Listener = socket(PF_INET, SOCK_STREAM, ppe->p_proto)) == INVALID_SOCKET)
{
m_chat += "Initialize Socket Listener Failed!\r\n";
UpdateData(false);
return;
}
//绑定IP及端口
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(m_port);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(Listener, (struct sockaddr *)&saddr, sizeof(saddr)))//成功返回0,失败返回-1.
{
m_chat += "Bind to IPEndPoint Failed! (Port in use?)\r\n";
UpdateData(false);
return;
}
//开始监听,队列长度1(不考虑多客户端)
if (listen(Listener, 1))
{
m_chat += "Listen Failed!\r\n";
UpdateData(false);
return;
}
m_chat += "Socket Server Started!\r\n";
UpdateData(false);
listening = true;
AfxBeginThread(Wait4Client, this);//另起线程等待客户端连接
}
//等待来自客户端的连接请求
UINT Wait4Client(LPVOID pParam)//LPVOID:一个没有类型的指针
{
CMFC_SocketServerDlg * c = (CMFC_SocketServerDlg *)pParam;
struct sockaddr_in caddr;
int caddrlen = sizeof(caddr);
c->toClient = accept(c->Listener, (struct sockaddr *)&caddr, &caddrlen);
if (c->toClient == INVALID_SOCKET)//异常处理
{
if (!c->listening)return 0;//若为服务器端主动关闭,则直接返回
c->m_chat += "Connect Failed!\r\n";
c->UpdateData(false);
return -1;
}
else
{
c->connected = true;
AfxBeginThread(ReceiveMessage, c);//连接建立,另起线程用于接收信息
c->m_chat += "Client: ";
c->m_chat += inet_ntoa(caddr.sin_addr);
c->m_chat += " Connected!\r\n";
c->m_ip = inet_ntoa(caddr.sin_addr);
c->UpdateData(false);
}
return 0;
}
//用于循环接收信息的线程
UINT ReceiveMessage(LPVOID pParam)
{
CMFC_SocketServerDlg * c = (CMFC_SocketServerDlg *)pParam;
char buffer[1024];
int error;//记录recv函数返回值,即接收的字节数,也作异常代码
while (error = recv(c->toClient, buffer, 1024, 0))
{
if (error == 0 || error == SOCKET_ERROR)break;
c->PrintData("Received Data", (unsigned char*)buffer, error);
c->aes.InvCipher((void *)buffer, error);//解密,恢复明文
c->PrintData("Unencrypted Data", (unsigned char*)buffer, error);
c->m_chat += "Client:";
c->m_chat += buffer;
c->m_chat += "\r\n";
c->UpdateData(false);
}
c->m_ip = "Not Connected...";
c->UpdateData(false);
if (!c->connected)return 0;//服务器端主动关闭,直接返回
closesocket(c->toClient);
c->connected = false;
c->m_chat += "Client Disconnected...\r\n";
c->UpdateData(false);
AfxBeginThread(Wait4Client, c);
return 0;
}
5 个解决方案
#1
Multiple Threads in the User Interface
http://msdn.microsoft.com/zh-cn/library/ms810439.aspx
《Windows核心编程》
《Windows核心编程》
#2
你把所有的UpdateData(),注释掉就不会出错了,主要是窗口指针刷新时候出现了,意外,自己仔细查看是哪个UpdateData出现的
#3
原因是什么?
怎么处理?
#4
我自己找到解决方法了。
原因如下:
当创建窗口的线程和UpdateData调用所在的线程不是同一线程的时候MFC就会出错。为MFC把部分信息储存在线程的TLS中,这些信息对于MFC的执行非常重要,因此MFC会在很多代码里面检查线程状态是否正确。当在线程中调用父窗口的UpdateData时,相对于UpdateData的线程环境已经改变了,所以就会出错了。
可以使用如下方案:
1,在线程中使用 pDLG->GetDlgItem(ID)->SetWindowText(str)
#5
线程调用父窗口一般采用SendMessage的方法
#1
Multiple Threads in the User Interface
http://msdn.microsoft.com/zh-cn/library/ms810439.aspx
《Windows核心编程》
《Windows核心编程》
#2
你把所有的UpdateData(),注释掉就不会出错了,主要是窗口指针刷新时候出现了,意外,自己仔细查看是哪个UpdateData出现的
#3
你把所有的UpdateData(),注释掉就不会出错了,主要是窗口指针刷新时候出现了,意外,自己仔细查看是哪个UpdateData出现的
原因是什么?
怎么处理?
#4
你把所有的UpdateData(),注释掉就不会出错了,主要是窗口指针刷新时候出现了,意外,自己仔细查看是哪个UpdateData出现的
我自己找到解决方法了。
原因如下:
当创建窗口的线程和UpdateData调用所在的线程不是同一线程的时候MFC就会出错。为MFC把部分信息储存在线程的TLS中,这些信息对于MFC的执行非常重要,因此MFC会在很多代码里面检查线程状态是否正确。当在线程中调用父窗口的UpdateData时,相对于UpdateData的线程环境已经改变了,所以就会出错了。
可以使用如下方案:
1,在线程中使用 pDLG->GetDlgItem(ID)->SetWindowText(str)
#5
你把所有的UpdateData(),注释掉就不会出错了,主要是窗口指针刷新时候出现了,意外,自己仔细查看是哪个UpdateData出现的
我自己找到解决方法了。
原因如下:
当创建窗口的线程和UpdateData调用所在的线程不是同一线程的时候MFC就会出错。为MFC把部分信息储存在线程的TLS中,这些信息对于MFC的执行非常重要,因此MFC会在很多代码里面检查线程状态是否正确。当在线程中调用父窗口的UpdateData时,相对于UpdateData的线程环境已经改变了,所以就会出错了。
可以使用如下方案:
1,在线程中使用 pDLG->GetDlgItem(ID)->SetWindowText(str)
线程调用父窗口一般采用SendMessage的方法