首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

vc socket采用异步多线程有关问题,请高手帮忙解答

2012-01-08 
vc socket采用异步多线程问题,请高手帮忙解答?我要完成的是服务器端等待客户端连接,当有客户端请求连接时,

vc socket采用异步多线程问题,请高手帮忙解答?
我要完成的是服务器端等待客户端连接,当有客户端请求连接时,服务器就建立一个线程来处理客户端的连接服务器继续等待其他客户端的连接。线程还要处理把客户端传来的数据存进数据库并把结果返回给客户端。客户端大概有六十个不间断的连接服务器。因我是新手初学者对socket   多线程不了解所以这个程序对我来说很难,请求大家高手们帮帮我谢谢。我写了一个大概请大家帮我改正完善它谢谢。
我采用异步多线程的方式,线程方面我不会写还请高手帮我。
以下是代码:

这部分是创建socket
void   CServerDlg::OnButton1()  
{
//   TODO:   Add   your   control   notification   handler   code   here
ADO.OnInitADOConn();
//初始化与绑定服务器
        WSADATA   wsaData;
        int   iErrorCode;
        if   (WSAStartup(MAKEWORD(2,1),&wsaData))   //调用Windows   Sockets   DLL
{  
                  m_list.InsertString(0, "初始套接字失败! ");
                  WSACleanup();
                  return;
}

m_list.InsertString(0, "服务器开始创建SOCKET。 ");

ServerSocket=socket(PF_INET,SOCK_STREAM,0);         //创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信

        if(ServerSocket   ==   INVALID_SOCKET)
{
                  m_list.InsertString(0, "无法创建服务器socket! ");
  WSACleanup();
                  return;
}

        m_sockServerAddr.sin_family   =   AF_INET;
        m_sockServerAddr.sin_addr.s_addr=inet_addr( "192.168.0.109 ");   //INADDR_ANY;       //向所有的IP地址发送消息
        m_sockServerAddr.sin_port   =   htons(8001);

  if   (bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr))   ==   SOCKET_ERROR)   //与选定的端口绑定
        {
      m_list.InsertString(0, "无法绑定服务器。 ");
      closesocket(ServerSocket);
      WSACleanup();
              return;
}

        m_list.InsertString(0, "服务器端口:8001. ");

        iErrorCode=WSAAsyncSelect(ServerSocket,m_hWnd,WM_CLIENT_ACCEPT,FD_ACCEPT);
                  //   产生相应传递给窗口的消息为WM_SERVER_ACCEPT   ,这是自定义消息

        if   (iErrorCode   ==   SOCKET_ERROR)  
{
                  m_list.InsertString(0, "WSAAsyncSelect设定失败!——用于连接请求的消息 ");
                  return;
}

        if   (listen(ServerSocket,5)   ==   SOCKET_ERROR)   //开始监听客户连接请求
{
m_list.InsertString(0, "服务器监听失败! ");
                return;
}

IsTrue   =   TRUE;

  m_list.InsertString(0, "服务器绑定监听成功。 ");
GetDlgItem(IDC_BUTTON1)-> EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON2)-> EnableWindow(TRUE);
}
//这是关闭socket
void   CServerDlg::OnButton2()  
{
//   TODO:   Add   your   control   notification   handler   code   here
ADO.ExitConnect();
//当程序退出时,把SOCKET清空
closesocket(ServerSocket);
WSACleanup();
m_list.InsertString(0, "服务器停止! ");


GetDlgItem(IDC_BUTTON1)-> EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON2)-> EnableWindow(FALSE);
}
//这是自定义连接事件
LRESULT   CServerDlg::OnAccept(WPARAM   wParam,   LPARAM   lParam)
{
//自定义接收客户机请求的消息       ON_MESSAGE(WM_CLIENT_ACCEPT,OnAccept)
if   (WSAGETSELECTERROR(lParam))
{
m_list.InsertString(0, "Error   detected   on   entry   into   OnServerAccept. ");
return   0L;
}

if(WSAGETSELECTEVENT(lParam)   ==   FD_ACCEPT)//如果
{
        Client   =   accept(ServerSocket,(LPSOCKADDR)&m_sockClientAddr,0);
//是不是在这里创建线程

AfxBeginThread(AcceptThreadProc,(LPVOID)&Client,0,0,0,NULL);

/*         if   (Client   ==   INVALID_SOCKET)
{
m_list.InsertString(0, "Server   socket   failed   to   accept   connection. ");
return   0L;
}
int   len=sizeof(m_sockClientAddr);
getpeername(   Client,(LPSOCKADDR)&m_sockClientAddr,&len);
CString   add;
add=inet_ntoa(m_sockClientAddr.sin_addr);
m_list.InsertString(0,add+ "工作站连接上了服务器。 ");

WSAAsyncSelect(Client,m_hWnd,WM_CLIENT_READCLOSE,FD_READ|FD_CLOSE);

IsTrue   =   TRUE;*/
}

return   0L;
}
//这是自定义事件读和关闭
LRESULT   CServerDlg::OnReadClose(WPARAM   wParam,   LPARAM   lParam)
{
//自定义的关闭与缓冲区有消息
if(!IsTrue)
{
m_list.InsertString(0, "有数据到达,但是没有工作站连接。 ");
}

CString   str;
switch   (WSAGETSELECTEVENT(lParam))
{
case   FD_READ:
{
if(recv(Client,(char   *)&msg,sizeof(msg),0)   ==   SOCKET_ERROR)
{
m_list.InsertString(0, "接收数据发生错误。 ");
return   0;
}
str.Format( "%s ",msg.msg);
m_list.InsertString(0,str);  
/*_bstr_t   sql= "select   *   from   Act_Tickets   where   cTicketNum= ' "+str+ " ' ";
rs=ADO.GetRecordSet(sql);
int   i=ADO.GetRecordCount(rs);
CString   s;
if(i> 0){
s= "真票 ";
}else{
s= "没有此票信息 ";
}
strcpy(msg.msg,s);*/
int   i=ADO.CallProc(str);
CString   a;
a.Format( "%d ",i);
strcpy(msg.msg,a);
//AfxMessageBox(a);
send(Client,(char   *)&msg,sizeof(msg),0);
break;
}
case   FD_CLOSE:
CString   add;
add=inet_ntoa(m_sockClientAddr.sin_addr);
str   =   _T( "工作站退出。 ");
m_list.InsertString(0,add+str);
closesocket(Client);
IsTrue   =   FALSE;
break;
}
return   0L;
}


//我写的线程函数不对不可以成为类成员函数不知怎么解决

//DEL   UINT   CServerDlg::AcceptThreadProc(LPVOID   pParam)
//DEL   {
//DEL   SOCKET   ClientSocket=(SOCKET)(LPVOID)pParam;  
//DEL     if   (ClientSocket   ==   INVALID_SOCKET)
//DEL   {
//DEL   m_list.InsertString(0, "Server   socket   failed   to   accept   connection. ");
//DEL   return   0L;
//DEL   }
//DEL   int   len=sizeof(m_sockClientAddr);
//DEL   getpeername(   ClientSocket,(LPSOCKADDR)&m_sockClientAddr,&len);
//DEL   CString   add;
//DEL   add=inet_ntoa(m_sockClientAddr.sin_addr);


//DEL   m_list.InsertString(0,add+ "工作站连接上了服务器。 ");
//DEL   //创建线程
//DEL   //getpeername(ServerSocket,(struct   sockaddr   FAR   *)&m_sockClientAddr,&len);
//DEL   WSAAsyncSelect(Client,m_hWnd,WM_CLIENT_READCLOSE,FD_READ|FD_CLOSE);
//DEL  
//DEL   IsTrue   =   TRUE;
//DEL  
//DEL   return   0;
//DEL   }
//还请高手帮帮我谢谢了。

[解决办法]
正确的是:
static DWORD WINAPI AcceptThreadProc( LPVOID pParam );
或者定义成全局的函数
DWORD WINAPI AcceptThreadProc( LPVOID pParam );
[解决办法]
个人建议,请参考,以FD_READ为例:
获得FD_READ消息后开始线程处理
AfxBeginThread(HandleFon,&m_sockClient,THREAD_PRIORITY_LOWEST );

HandleFon是线程处理函数,
m_sockClient是Accept返回的socket,

在ServerDlg.cpp开头声明
UINT HandleFon(LPVOID lparam);
.........................
UINT HandleFon(LPVOID lparam)
{
SOCKET* socket = (SOCKET*)lparam;//获得传递过来的m_sockClient

//如果是对话框程序,用下句获得CServerDlg指针
CServerDlg *pFrame=(CServerDlg*)AfxGetApp()-> m_pMainWnd;

//否则先获得应用程序指针,再指向CServerDlg,假设应用程序类CMyApp
CMyApp *pFrame=(CMyApp*)AfxGetApp()-> m_pMainWnd;
CServerDlg *pSdlg=pFrame-> GetServerDlg();//GetServerDlg()是自定义获取CServerDlg类指
//针的函数.
......................
//接下来就可以使用CServerDlg中公有成员了.
}
不知道是否是你需要的,仅供交流参考:)
有出错的地方请各位指正,谢谢.

热点排行