客户端定时连接服务器,但若连接不上等待时间太长了,程序动不了,像死了一样,请问如何开线程进行连接?或者用其他方法。多谢大家拉
解决方案 »
- 导出数据到excel
- 如何将一个LPCSTR转成CString类型,在线等
- 实现com接口的时候,各个Ixxxx之间没有顺序关系,为什么调用时要注意顺序?
- 把文档保存为图片,急!!!!!!!!!!!!
- 请教好的算法!!!
- MSXML 插入新结点的问题。
- 有关数据库的创建
- 豁出家当重分悬赏——一个功能授权和密码管理的问题(有满意答案可另给分—代妹妹问的问题)
- 用例图中,<<include>> 和 <<extend>> 的区别是什么
- 求教:VC中如何调用MATLAB中的imshow();等图像显示函数
- try,catch的奇怪问题
- 请lop5712(LOP)等帮忙 SendMessage为什么会不起作用???????? 还是没有解决!!!!!
{
DECLARE_DYNCREATE(CRcvDataThread)
private://variable
CFtpCmdCtrl m_FtpCmdCtrl; //继承自MFC的SOCKET类
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CRcvDataThread)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
virtual int Run();
//}}AFX_VIRTUAL// Implementation
// Generated message map functions
//{{AFX_MSG(CRcvDataThread)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};
int CRcvDataThread::Run()
{
// TODO: Add your specialized code here and/or call the base class
if(!m_FtpCmdCtrl.Create())
return CWinThread::Run();
if(!m_FtpCmdCtrl.AsyncSelect())
return CWinThread::Run();
if(m_FtpCmdCtrl.Connect(strFtpServerName,usServerPort))
return CWinThread::Run();
return CWinThread::Run();
}
it goes a little something like this:////////////////////////////////////////////////////
class CMyThread: public CWinThread
{
// yadda yadda yadda CMySocket m_ClientSocket; // yadda yadda yadda
}
////////////////////////////////////////////////////... and ...////////////////////////////////////////////////////
class CClientSocket: public CSocket
{
// yadda yadda yadda CMyThread* m_ParentThread; // yadda yadda yadda
}
// Global used for passing socket to a diffr thread
SOCKET Glob_hConnectedSocket;
////////////////////////////////////////////////////... and ...////////////////////////////////////////////////////
class CServerSocket: public CSocket
{
// yadda yadda yadda // Attributes
public:
CObList m_clients; // Current Clients // Overridables
protected:
virtual void OnAccept(int nErrorCode); // yadda yadda yadda};
////////////////////////////////////////////////////... then ...////////////////////////////////////////////////////
void CServerSocket::OnAccept(int nErrorCode)
{
CSocket sConnected;
if(Accept(sConnected))
{
// Find out who we are talking to
CString strAddr;
UINT nPort; if(sConnected.GetPeerName(strAddr, nPort))
TRACE2("CONNECTED: %s, port %d\n", strAddr, nPort); // Detach Socket; save in global variable
Glob_hConnectedSocket = sConnected.Detach(); // Launch new thread to handle this connection
// also, create initially suspended
CSockThread* pClientThread = (CMyThread*)
AfxBeginThread(
RUNTIME_CLASS(CMyThread),
THREAD_PRIORITY_NORMAL, 0,
CREATE_SUSPENDED, NULL ); // Add Client to server socket's client list
// You'll need to delete the CMyThread objects
m_clients.AddTail(pClientThread); // Set client thread's m_bAutoDelete to FALSE;
// we will clean up with CWinThread object ourselves
pClientThread->m_bAutoDelete = FALSE; // Resume the thread for execution
pClientThread->ResumeThread();
}
else
{
// This would be unusual
TRACE("CServerSocket::OnAccept()- Accept Failed!\n");
return;
}
}
////////////////////////////////////////////////////... and ...////////////////////////////////////////////////////
BOOL CMyThread::InitInstance()
{
// Attach socket object to socket handle
if(m_ClientSocket.Attach(Glob_hConnectedSocket) == FALSE)
return FALSE;
// Set Parent Thread property of socket
m_ClientSocket.m_ParentThread = this; // Successful
return TRUE;
}
////////////////////////////////////////////////////Basically, you must detach the socket and attach back to it
in the context of the thread you want to control it.In the case above, the listening socket that accepts connections is
serialized -- so the Glob_hConnectedSocket handle won't ever be used
by more than one thread at a time.
谢谢!有谁有更具体的代码?马上揭帖。
如果是一个线程读另一个线程发送,则没有任何问题,因为SOCKET本来就支持迸发进行的。
:(
偶的意思是,你再线程中用这个Socket连接到服务器,那么要给服务器发送数据时不是要用到这个Socket么? 但你这个Socket对象是作为线程类中的一个成员创建中的,现在我要在主线程中发送数据,应该如何调用呢?
==================
简单,开辟一个缓冲区,主线程放数据,发送线程取数据。
不过,我不明白,为什么你的Socket对象要在线程中临时创建呢?你可声明在主线程,在子线程中去create bind send等等。这样,你在子线程中也可以调用父类的发送函数。
我的程序是分模块的,Socket由我创建,但其他人写的模块可以调用,因此发送数据的时候一定是在主线程中的。我这里要解决的就是连接的时候不能像死机一样。
MSG msg;
Sleep( 5 );
if ( ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE ) )
{
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}其次,因为线程中操作还会出现关闭套接字等问题,最好在每个用到CSocket对象的线程中要运行一次以下代码:
#ifndef _AFXDLL
#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define _afxSockThreadState AfxGetModuleThreadState()
// setup maps and lists specific to socket state
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
if (pState->m_pmapSocketHandle == NULL)
pState->m_pmapSocketHandle = new CMapPtrToPtr;
if (pState->m_pmapDeadSockets == NULL)
pState->m_pmapDeadSockets = new CMapPtrToPtr;
if (pState->m_plistSocketNotifications == NULL)
pState->m_plistSocketNotifications = new CPtrList;
#endif如果套接字不是在线程中创建,而是在线程中调用另外的类中的对象来创建的话,删除时,可能会用到Attach函数.以下为在线程中连接服务器并保持连接的线程函数,仅供参考(套接字对象在另外的类中创建)
UINT ConnectThread(LPVOID lpParam)
{
CVFMDlg *pDlg = (CVFMDlg*)lpParam; #ifndef _AFXDLL
#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define _afxSockThreadState AfxGetModuleThreadState()
// setup maps and lists specific to socket state
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
if (pState->m_pmapSocketHandle == NULL)
pState->m_pmapSocketHandle = new CMapPtrToPtr;
if (pState->m_pmapDeadSockets == NULL)
pState->m_pmapDeadSockets = new CMapPtrToPtr;
if (pState->m_plistSocketNotifications == NULL)
pState->m_plistSocketNotifications = new CPtrList;
#endif pDlg->ConnectVFMServ(); time_t tVFMCurrent;
CClientSocket *pSocket = NULL; HANDLE hEvent = pDlg->m_hEvtStop;
DWORD dwWaitResult;
while (TRUE)
{
MSG msg;
Sleep( 5 );
if ( ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE ) )
{
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}
dwWaitResult = WaitForSingleObject(hEvent, 5);
if ( dwWaitResult == WAIT_OBJECT_0 )
{
break;
}
time(&tVFMCurrent);
pSocket = pDlg->m_pVFMSocket;
// ¼ì²éÁ¬½Ó״̬
if ( !pDlg->m_bConnectVFMSucc )
{
if ( (tVFMCurrent - pDlg->m_tLastConnVFMServerTime) > pDlg->m_config.nRepeatTime )
{
pDlg->ConnectVFMServ();
}
continue;
}
}
return 0;
}如果不想有上述的麻烦,建议自己写一个类,就不用担心线程中收不到信息(用事件而且用消息)
用select()函数!
我的程序是分模块的,Socket由我创建,但其他人写的模块可以调用,因此发送数据的时候一定是在主线程中的。我这里要解决的就是连接的时候不能像死机一样。
--------------------------------------------
其实,如果在主线程中进行,不但是连接象死机,发送、接收都有可能象死机的。因为是阻塞调用,除非你用AsySocket类。在主线程中发数据,与在子线程中发数据没有什么区别,而且更容易处理界面上的事。
不过,你上面说的我不是十分明白。如果真要在主线程中发数据,你只是想解决连接时别象死机,你完全可以在一个线程中去创建、连接,连接成功后再通知主线程(比如采用CEvent类等)可以发送数据了。(这样的思路想起来真有点怪呢)
www.codeproject.com
www.codeguru.com
CC