使用 TCP 套接字 (WIN32 API) 创建的两个窗口之间的通信

Posted

技术标签:

【中文标题】使用 TCP 套接字 (WIN32 API) 创建的两个窗口之间的通信【英文标题】:Communication between two windows created using TCP Sockets (WIN32 API) 【发布时间】:2013-03-02 04:57:28 【问题描述】:

我想使用 WINAPI 创建两个窗口,然后我想使用 TCP scoket 在它们之间进行通信。 到目前为止,我已经成功创建了两个窗口,并且也成功打开了套接字。但是两个窗口将如何使用这个套接字进行通信?这是我到目前为止写的代码:

另一个问题是代码只从服务器向客户端发送一次数据。除非数据从服务器向客户端发送一次,否则不会处理其他 Windows 消息:( 有人帮帮我吗?enter code here服务器窗口:

// Program Name: server_window
// ===============================
// Author Name: Ayesha Hassan
// ===============================
// The Program creates a Listening Socket and waits for the client.
// As soon as a Client is connected to this Server's Listening Socket, a Window is launched.      
// When the user Clicks on this window using Mouse, a Message is sent to the Client over the Connected Socket. 

#include <windows.h>
#include <iostream.h>
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <tchar.h>
#include "resource.h"
#pragma comment(lib,"ws2_32.lib")

SOCKET AH_GlbSocket;

const char AH_GlbClassName[] = "myWindClass";   ///Window Class Name
HWND AH_Glb_hwnd;   //Header to Window

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
            WPARAM wParam, LPARAM lParam)

char message[]="Mouse Clicked On SERVER Window";
HDC hdc;

//Gets Handle for the Window 
hdc=GetDC(hwnd);

char buffer[1000];
memset(buffer,0,999);

   switch(msg)
      

      case WM_LBUTTONDOWN:
      //Sends Text to be displayed oon Client Window
         send(AH_GlbSocket, message, strlen(message), 0);
         break;

      case WM_CREATE:
          
             WSADATA WsaDat;
             if(WSAStartup(MAKEWORD(2,2), &WsaDat)!=0)
                
                   //printf("WSA Initialization failed!\r\n");
                   WSACleanup();
                   system("PAUSE");
                   return 0;
                

                AH_GlbSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                if(AH_GlbSocket == INVALID_SOCKET)
                   
                      //printf("AH_GlbSocket creation failed.\r\n");
                      WSACleanup();
                      system("PAUSE");
                      return 0;
                   
                //else
                   //printf("Socket created.\n");

                SOCKADDR_IN serverInf;
                serverInf.sin_family = AF_INET;
                serverInf.sin_addr.s_addr = INADDR_ANY;
                serverInf.sin_port = htons(8888);

                if(bind(AH_GlbSocket,(SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR)
                   
                      //printf("Unable to bind AH_GlbSocket!\r\n");
                      WSACleanup();
                      system("PAUSE");
                      return 0;
                   

                listen(AH_GlbSocket, 1);
                SOCKET TempSock = SOCKET_ERROR;

                while(TempSock == SOCKET_ERROR)
                
                   //printf("Waiting for incoming connections...\n\n");
                  TempSock = accept(AH_GlbSocket, NULL, NULL);
                
                AH_GlbSocket = TempSock;


         
         break;
      case WM_CLOSE:
         DestroyWindow(hwnd);
         break;

      case WM_DESTROY:
         PostQuitMessage(0);
         break;

      default:
         return DefWindowProc(hwnd, msg, wParam, lParam);
      
    return 0;


int WINAPI WinMain(  HINSTANCE hInstance, 
  HINSTANCE hPrevInstance, 
  LPSTR lpCmdLine, 
  int nShowCmd )



   WNDCLASSEX wc;
   MSG Msg;

   //Step 1: Registering the Window Class
   wc.cbSize        = sizeof(WNDCLASSEX);
   wc.style         = 0;
   wc.lpfnWndProc   = WndProc;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 0;
   wc.hInstance     = NULL;
   wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = AH_GlbClassName;
   wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);  
   //wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
   //wc.hIcon  = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
   //wc.hIconSm  = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 26, 26, 0);

   if(!RegisterClassEx(&wc))
   
      MessageBox(NULL, "Window Registration Failed!", "Error!",
                  MB_ICONEXCLAMATION | MB_OK);
      return 0;
   

   // Step 2: Creating Window1
   AH_Glb_hwnd = CreateWindowEx( WS_EX_CLIENTEDGE,
                                 AH_GlbClassName,
                                 "I am SERVER Window",
                                 WS_OVERLAPPEDWINDOW,
                                10,30, 540, 220,
                                 NULL, NULL, NULL, NULL);
   if(AH_Glb_hwnd == NULL)
   
      MessageBox(NULL, "Window Creation Failed!", "Error!",
                 MB_ICONEXCLAMATION | MB_OK);
      return 0;
   

   ShowWindow(AH_Glb_hwnd,SW_SHOWDEFAULT);
   UpdateWindow(AH_Glb_hwnd);

   // Step 3: The Message Loop
   while(GetMessage(&Msg, NULL, 0, 0) > 0)
   
      TranslateMessage(&Msg);
      DispatchMessage(&Msg);
   
   return Msg.wParam; 





***CLIENT WINDOW:***
#include <windows.h>
#include "stdafx.h"
//#include <iostream.h>
#include <winsock2.h>
#include <stdio.h>
#include "resource.h"
#pragma comment(lib,"ws2_32.lib")

SOCKET AH_Glb_Socket;

const char AH_Glb_ClassName[] = "myWindClass";
HWND AH_Glb_hwnd;


// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)



    switch(msg)
    

        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);

    
    return 0;




int WINAPI WinMain(  HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )

    // Initialise Winsock
    WSADATA WsaDat;  

    if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
    
        printf("Winsock error - Winsock initialization failed");
        WSACleanup();
        system("PAUSE");
        return 0;
    
    char* buff="CLIENT says: I am Going to connect to the server now\n\n";
    printf(buff,sizeof(buff));
    // Create our socket
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(Socket==INVALID_SOCKET)
    
        printf("Winsock error - Socket creation Failed!\r\n");
        WSACleanup();
        system("PAUSE");
        return 0;
    

    // Resolve IP address for hostname
    struct hostent *host;
    if((host=gethostbyname("localhost"))==NULL)
    
        printf("Failed to resolve hostname.\r\n");
        WSACleanup();
        system("PAUSE");
        return 0;
    

    // Setup our socket address structure
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port=htons(8888);
    SockAddr.sin_family=AF_INET;
    SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr);

    // Attempt to connect to server
    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr))!=0)
    
        printf("Failed to establish connection with server\r\n");
        WSACleanup();
        //system("PAUSE");
        //return 0;
    

    WNDCLASSEX wc;

    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = NULL;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = AH_Glb_ClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    //wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
    //wc.hIcon  = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
    //wc.hIconSm  = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 26, 26, 0);

    if(!RegisterClassEx(&wc))
    
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    

    // Step 2: Creating Window1
    AH_Glb_hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        AH_Glb_ClassName,
        "I am CLIENT Window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 440, 120,
        NULL, NULL, NULL, NULL);

    if(AH_Glb_hwnd == NULL)
    
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    

    ShowWindow(AH_Glb_hwnd,SW_SHOWDEFAULT);
    UpdateWindow(AH_Glb_hwnd);

    char buffer[1000];
    memset(buffer,0,999);

        recv(Socket,buffer,1000,0);
        printf(buffer,sizeof(buffer));
        TextOut(GetDC(AH_Glb_hwnd),5,5,buffer,sizeof(buffer));


    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
       
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    
    return Msg.wParam;



【问题讨论】:

您似乎已经找到了 WinSOCK API 的每个部分,除了 send() 和 recv() 函数。 在连接的套接字上接收到数据时是否生成任何 Windows 消息? (如创建窗口时生成 WM_CREATE 消息)。如果windows每次在连接的socket上接收到数据时都会生成这样的消息,我的任务会变得容易得多。 很抱歉提出愚蠢的问题 :( 我是 Windows 编程新手。 对此的简单回答是,您不应将 Windows GUI 编程与网络编程混为一谈。所有的网络编程都应该在一个单独的线程上完成。没有与网络相关的 WM_* 消息。您可能还会被告知,在这个后期阶段,您不应该直接使用 Windows GUI 消息,而应该使用 AFX 之类的顶层。 知道了 :) 我仍然不知道如何创建线程 :( 【参考方案1】:

尝试使用 WSAAsyncSelect 建立基于消息的连接;这样您就可以在程序运行时继续发送/接收消息。

更多关于 WSAAsyncSelect 函数的信息在这里: http://msdn.microsoft.com/en-us/library/windows/desktop/ms741540%28v=vs.85%29.aspx

codeproject.com 上还有一个关于使用 WIN32 API + winsock 的优秀教程:http://www.codeproject.com/Articles/13071/Programming-Windows-TCP-Sockets-in-C-for-the-Begin

如果您遵循教程,包括注册窗口消息,您应该能够多次从服务器向客户端发送数据,反之亦然,直到套接字关闭。

希望对你有帮助。

Mmarss

【讨论】:

非常感谢。这个教程真的帮了我很多:)

以上是关于使用 TCP 套接字 (WIN32 API) 创建的两个窗口之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

ESP-C3入门9. 创建TCP Server

ESP-C3入门9. 创建TCP Server

STM32F107VC 使用 TCP 运行 FreeRTOS

套接字没有创建win32 c++

在本机应用程序中使用 win32

创建可在另一种语言上调用的 win32api(dll) [关闭]