我在程序里只有一个线程,用来接收服务器(全局SOCKET)传来的数据,然后显示在标签上。如何按下窗体上的一个按扭,结束线程并关闭SOCKET。

解决方案 »

  1.   

    既然socket是全局的你只要在按钮中添加close函数再向线程发一个消息调用关闭线程的函数不就成了。
      

  2.   

    不要用指针去建立CSocket对象,按下窗体上的一个按扭先close Socket,然后关闭线程。
    如何终止线程的运行?
    (1) 线程函数返回(最好使用这种方法)。
    这是确保所有线程资源被正确地清除的唯一办法。
    如果线程能够返回,就可以确保下列事项的实现:
    •在线程函数中创建的所有C++对象均将通过它们的撤消函数正确地撤消。
    •操作系统将正确地释放线程堆栈使用的内存。
    •系统将线程的退出代码设置为线程函数的返回值。
    •系统将递减线程内核对象的使用计数。
    (2) 调用ExitThread函数(最好不要使用这种方法)。
    该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。
    (3) 调用TerminateThread函数(应该避免使用这种方法)。
    TerminateThread能撤消任何线程。线程的内核对象的使用计数也被递减。TerminateThread函数是异步运行的函数。如果要确切地知道该线程已经终止运行,必须调用WaitForSingleObject或者类似的函数。当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。
    (4) 包含线程的进程终止运行(应该避免使用这种方法)。
    由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。就像从每个剩余的线程调用TerminateThread一样。这意味着正确的应用程序清除没有发生,即C++对象撤消函数没有被调用,数据没有转至磁盘等等。
    一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用GetExitcodeThread来检查由hThread标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码。
      

  3.   

    哎,我用的SOCKET做的。
    // CMPP120Dlg.cpp : implementation file
    //#include "stdafx.h"
    #include "CMPP120.h"
    #include "CMPP120Dlg.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endifHANDLE hEvent;SOCKET mSock;
    CString iExit;
    //----------------------------------------
    UINT SocketThread( LPVOID pParam )
    {
    CCMPP120Dlg* dlg=(CCMPP120Dlg*)pParam;
    //定义接收缓存
    char mBuff[4096];
    CString s;
    int len=0;
        CStdioFile sFile;
    sFile.Open(_T("yourfilename.txt"),CStdioFile::modeCreate | CStdioFile::modeReadWrite);
    while(!(s=="exit"))
    {
    memset(mBuff,0x00,4096);
        len=recv(mSock,mBuff,4096,0);
    if (len>0)
    {
    mBuff[len]='\0';
                s=mBuff;
    iExit=mBuff;
    dlg->mRecv.SetWindowText(s); 
                sFile.WriteString(s+"\n"); 
        }        
    dlg->m_REC.SetWindowText(iExit); 
    Sleep(100);
    }
    closesocket(mSock);
    dlg->m_REC.SetWindowText(iExit); 
    sFile.Close(); 
    return 0;   // 返回并退出线程
    //或者调用void AfxEndThread( UINT nExitCode );来退出
    }
    //-------------------------------------
    BOOL CCMPP120Dlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); 
    CTime mTime;
    CString abc;
    //char* Abc;
    mTime=CTime::GetCurrentTime();
    //CTime time = CTime::GetCurrentTime();
    //wsprintf(Abc,"%0x",10);
    abc.Format("%0x",0xffffffff1);
    //abc=hex(100);
        abc = mTime.Format(_T("%A, %Y年%m月%d日%H%M%S, "));
    mHost="127.0.0.1";
    mPort=8801;
    struct sockaddr_in ISMGserver;
    ISMGserver.sin_family = AF_INET;
    ISMGserver.sin_port = htons(mPort);
    ISMGserver.sin_addr.s_addr=inet_addr(mHost);
    mSock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(mSock==INVALID_SOCKET){
    AfxMessageBox("error socket");
    return 0;
    } if(SOCKET_ERROR==connect(mSock,(struct sockaddr *)&ISMGserver,sizeof(ISMGserver))){
    AfxMessageBox("connect error");
    // return 0;
    }
      AfxBeginThread(SocketThread,this);
    return TRUE;  // return TRUE  unless you set the focus to a control
    }
      

  4.   

    在标签里PostQuitMessage()
    然后在PreTranslateMessage()里面:
    if (pMsg->message==WM_QUIT) 
       处理socket.....
      

  5.   

    xiaoxiaohan(萧晓寒) 有理,
      

  6.   

    我专门写了一个线程来终止这个线程也出现了一个怪事。因为涉及到同步的问题,我用了信号量,但是发现必须把对SOCKET的操作包括进去才行。
      

  7.   

    你的线程不能结束,不就因为:
        while(!(s=="exit"))
        {
          ...
        }
       你试试这样行不行:
       全局变量 bool m_bFlag;
       在你起线程前:m_bFlag=true;
       
       线程里:     
       while(m_bFlag)
       {
        ...
       }
     加一按钮事件:
       void CIPAddressDlg::OnButton1() 
      {
    m_gEvent=false;
      }  你的线程只要跳出循环,关闭socket你的代码里不是有么!
      

  8.   

    那好啊,你在那个按钮里写PostQuitMessage(1)然后在然后在PreTranslateMessage()里面:
    if (pMsg->message==WM_QUIT)
        关闭socket()你还要怎样详细????????
      

  9.   

    pMsg是怎么来的呀
    {  }里面怎么写呀?包括定义等等,我很菜,救命呀!!!!!
      

  10.   

    pMsg是怎么来的呀
    {  }里面怎么写呀?包括定义等等,我很菜,救命呀!!!!!
      

  11.   

    1.将线程的控制变量翻转,使线程能够退出。
    2.shutdown、closesocket、将你的Socket赋值为INVALID_SOCKET.
      

  12.   

    //Use WSAAsyncSelect. Here is an example:
    #include "c:\progra~1\devstu~1\vc\include\Windows.h"
    #include "stdio.h"
    #include "winsock.h"int count;
    HINSTANCE ghInstance;
    SOCKADDR_IN mAddrServer;LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain (HINSTANCE hInstance, 
      HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int iCmdShow){
    HWND hWnd;
    MSG msg;
    WNDCLASSEX wndclass;
    static char  szAppName[] = "HelloWin";
    ghInstance = hInstance;wndclass.cbSize = sizeof (wndclass);
    wndclass.style=CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon (hInstance,IDI_APPLICATION);
    wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclass.lpszMenuName =NULL;
    wndclass.lpszClassName =szAppName;
    wndclass.hIconSm = LoadIcon (NULL,IDI_APPLICATION);RegisterClassEx (&wndclass);hWnd = CreateWindow (
      szAppName,
      "The Hello Program",
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      NULL,
      NULL,
      hInstance,
      NULL);ShowWindow (hWnd, iCmdShow);
    UpdateWindow (hWnd);
    while (GetMessage(&msg,NULL,0,0))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    return msg.wParam;}WORD wVersionRequested;
    WSADATA wsaData;
    int  nErrorStatus;
    FILE *f;
    SOCKET s;
    SOCKADDR_IN addr;
    SOCKET clientS;
    SOCKADDR_IN ClientAddr;
    int nClientAddrLen;
    char str[200];
    int temp1;
    char buffer[200];LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
    {
      HDC hDC;
      PAINTSTRUCT ps;
      RECT rect;
      switch (iMessage)
      {
        case WM_CREATE:
           f = fopen ("c:\\debug.out","w");
           str[0]=0;       return 0;
        case WM_PAINT:
           hDC = BeginPaint (hWnd, &ps);
           GetClientRect (hWnd,&rect);
           DrawText (hDC, str, -1, &rect,
              DT_SINGLELINE | DT_CENTER | DT_VCENTER);
           EndPaint (hWnd, &ps);
           return 0;
        case WM_LBUTTONDOWN:
           wVersionRequested = MAKEWORD (2,0);
           nErrorStatus = WSAStartup (wVersionRequested, &wsaData);
           if (nErrorStatus != 0)
           {
               fprintf (f, "startup did not work");fflush(f);
           }
           s = socket(AF_INET, SOCK_STREAM, 0);
           if (s==INVALID_SOCKET) {
              fprintf (f, "socket stream error \n");fflush(f);
           }
           addr.sin_family=AF_INET;
           addr.sin_port = htons (1050);
           addr.sin_addr.s_addr = htonl (INADDR_ANY);
           temp1 = bind (s, (LPSOCKADDR) &addr,sizeof(addr));
           if (temp1==SOCKET_ERROR) {
              fprintf (f,"bind error %x\n",WSAGetLastError);fflush(f);
            }
            temp1 = listen (s,1);
            if (temp1==SOCKET_ERROR) {
              fprintf (f,"listen error %x\n",WSAGetLastError);fflush(f);
            }
            nClientAddrLen = sizeof (ClientAddr);
            temp1=WSAAsyncSelect(s,hWnd, WM_USER+1,FD_ACCEPT | FD_READ);
            fprintf (f, "async select %d\n",temp1);fflush(f);
            return 0;
      case WM_USER+1:
       if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT) {
            fprintf (f,"accepting\n");fflush(f);
            clientS = accept (s,(LPSOCKADDR) &ClientAddr, &nClientAddrLen);
            if (clientS == INVALID_SOCKET) {
              fprintf (f,"accept error %x\n",WSAGetLastError);fflush(f);
            }
            else {
              fprintf (f, "accepted\n");fflush(f);
              strcpy (str,"accepted\n");
              InvalidateRect(hWnd,NULL,TRUE);
            }
        }
        else
        if (WSAGETSELECTEVENT(lParam) == FD_READ ) {
           temp1 = recv(clientS,buffer,sizeof(buffer),0);
           fprintf (f, "temp1 %x received %x\n",temp1,WSAGetLastError());fflush(f);
           if (temp1 > 0 ){
             buffer[temp1]=0;
             strcat (str,buffer);
             InvalidateRect(hWnd,NULL,TRUE);
           }
        }
           return 0;
        
        case WM_DESTROY:
           break;
        default:
           return DefWindowProc (hWnd, iMessage, wParam, lParam);
      }
    return (0L);

      

  13.   

    SDK程序,你可以参考WSAAsyncSelect usage