How to reconcile MFC and API programming

Joseph Klasen 146 Reputation points
2022-09-14T18:55:53.547+00:00

I am attempting to code a simple peer-to-peer local network for a DirectX gaming environment. For all of my DirectX coding, I have been working with Windows API's no problem. However, while starting to code the basic Winsock code for the (very basic) local network, I seem to have swerved into MFC programming.

As soon as I began coding for Socket initialization, Visual Studio gave me a compiler error saying I needed to add #define _AFXDLL, which I did, but then I got the compile error:
c:\program files (x86)\microsoft visual studio 11.0\vc\atlmfc\include\afxv_w32.h(16): fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>

I have done very little programming with MFC - since DirectX deals directly with the API's, so I would like to ask how I can sort out Winsock programming in a non-MFC environment?

Also, since I am new to Microsoft Q&A forums, and I have not been able to find any guidance in the Q&A FAQ's for providing code snippets in questions, I am attaching a code snippet,
enter code here

// File: DOP Comm Utility.cpp

include "stdafx.h"

define _AFXDLL

ifndef FD_SETSIZE

define FD_SETSIZE 1024

endif

include <winsock2.h>

include <windows.h>

include <stdio.h>

include <math.h>

include <iostream>

include <time.h>

include <stdlib.h>

include <sys/types.h>

include <sys/timeb.h>

include <string.h>

using namespace std;

include <ws2tcpip.h>

define _CRT_SECURE_NO_WARNINGS 1

define _CRT_NONSTDC_NO_WARNINGS

include <iphlpapi.h>

include <afxsock.h>

// Need to link with Ws2_32.lib

pragma comment(lib, "ws2_32.lib")

pragma comment(lib, "IPHLPAPI.lib")

define ISVALIDSOCKET(s) (s != INVALID_SOCKET)

define CLOSESOCKET(S) closesocket(s)

define GETSOCKETERRNO() (WSAGetLastError())

define TIMEOUT 3.0

int _tmain(int argc, _TCHAR* argv[])
{
int j, k;
int AdapterFlag = 0;

char                    Term;  
char                    AdapterFind[200];  
char                    AddressFind[60];  

// Winsock WSAStartup & Initialization ----------------------------------------------------------------------------------------------

WORD wVersionRequested;  
WSADATA wsaData;  
int err;  

//Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h   

wVersionRequested = MAKEWORD(2, 2);  

err = WSAStartup(wVersionRequested, &wsaData);  
if (err != 0) {  
    printf("WSAStartup failed with error: %d\n", err);  
    cin.clear();  
    cin >> Term;  
    return 0;  
}  

//Confirm that the WinSock DLL supports 2.2.  
//Note that if the DLL supports versions greater than 2.2 in addition to 2.2, it will still return  
//2.2 in wVersion since that is the version we requested.                                        */  

if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {  

    printf("Could not find a usable version of Winsock.dll\n");  
    WSACleanup();  
    cin.clear();  
    cin >> Term;  
    return 0;  
}  
else  
    printf("The Winsock 2.2 dll has been initialized - WSAStartup completed\n");  

PIP_ADAPTER_ADDRESSES OwnAdapters;  
PIP_ADAPTER_ADDRESSES OurAdapter;  
DWORD Asize = 20000;  

do {  
        OwnAdapters = (PIP_ADAPTER_ADDRESSES) malloc (Asize);  

        if( !OwnAdapters )  
        {  
            printf( "could not allocate memory for Adapters \n" );  
            WSACleanup();  
            cin.clear();  
            cin >> Term;  
            return 0;  
        }  

        int R = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, 0, OwnAdapters, &Asize );  

        if( R == ERROR_BUFFER_OVERFLOW )  
        {  
            printf("GetAdaptersAddresses needs larger buffer.\n" );  
            free( OwnAdapters );  
        }  
        else  
            if( R == ERROR_SUCCESS )  
            {  
                break;  
            }  
            else  
            {  
                printf( "Error from GetAdaptersAddresses call: %d\n", R );  
                 WSACleanup();  
                 free( OwnAdapters );  
                 cin.clear();  
                 cin >> Term;  
                 return 0;  
            }  
    } while (!OwnAdapters);  

// Loop through the OwnAdapters linked list and print information for each adapter and address  


PIP_ADAPTER_ADDRESSES Adapters = OwnAdapters;  
char AP[100];  

while (Adapters)  
{  
    printf( "\nAdapter mame:  %S", Adapters->FriendlyName );  
    printf( "\n" );  

    PIP_ADAPTER_UNICAST_ADDRESS Address = Adapters->FirstUnicastAddress;  
    while( Address )  
    {  
        printf( "\t%s", Address->Address.lpSockaddr->sa_family == AF_INET ? "IPv4"  :  "IPv6");  

        //char AP[100];  

        getnameinfo( Address->Address.lpSockaddr, Address->Address.iSockaddrLength, AP, sizeof(AP), 0, 0, NI_NUMERICHOST );  
        printf( "\t%s\n", AP );  

        if( ( AdapterFlag == 1 ) && ( Address->Address.lpSockaddr->sa_family == AF_INET ) )  
        {  
            for( j = 0; j < sizeof(AP); j++ )  
            {  
                OurAddress[j] = AP[j];  
            }  
            AdapterFlag = -1;  
            printf( "\t", "Our Address: " );  
            printf( "\t%s\n", OurAddress);  
        }  


        Address = Address->Next;  
    }  
    Adapters = Adapters->Next;  
}  

printf("\n\nFD_SETSIZE is %d.\n", FD_SETSIZE);  


SOCKET              MainClient;  
bool                SocketErr;  
struct sockaddr_in  MainData;  
char                localIP[50] = "155.33.5.100";  


MainClient = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );  

if( !ISVALIDSOCKET( MainClient ) )  
{  
    printf( "\nThe MainClient Socket did not validate. \n" );  
    cin.clear();  
    cin >> Term;  
    free( OwnAdapters );  
    WSACleanup();  
    return 0;  
}  

MainData.sin_family = AF_INET;  

MainData.sin_addr.s_addr = inet_addr(localIP);  

MainData.sin_port = htons(4400);  

if( bind( MainClient, (SOCKADDR *) &MainData, sizeof( MainData) ) == SOCKET_ERROR )  
{  
    printf( "\nThe MainClient Socket did not successfuly BIND. \n" );  
    cin.clear();  
    cin >> Term;  
    free( OwnAdapters );  
    WSACleanup();  
    return 0;  
}  


cin.clear();  
cin >> Term;  

free( OwnAdapters );  
WSACleanup();  

return 0;  

}

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,580 questions
{count} votes

Accepted answer
  1. Michael Taylor 53,496 Reputation points
    2022-09-14T19:03:53.713+00:00

    No you shouldn't be defining that _AFXDLL yourself. It appears you're trying to add MFC to an existing project and that isn't going to end well. A lot of the MFC settings are managed through the project properties (including the aforementioned _AFXDLL). That macro tells the compiler that MFC is provided in a standalone DLL and it shouldn't try to add the code to your project. This is the default and preferred approach. But there is a project setting for that you need to set instead (Use MFC, if I recall correctly).

    Be aware that you don't need to use MFC to work with Winsock. You can continue to rely on Win32 and/or a third party library. Only add MFC if you want to take advantage of the UI libraries that MFC provides. If you are going to go this route then you have to set up a lot of infrastructure to bootstrap the MFC infrastructure. It is way too much code to manually add to a project. Create a new MFC project based upon your needs (EXE, DLL, etc) and then add your custom code to it. If you don't get the code properly synced up with your compiler options and linked with the right libraries then it is very difficult to figure out what is going wrong.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. rtischer8277 41 Reputation points
    2022-09-19T13:14:44.3+00:00

    Also be aware that current MFC's socket class, CAsyncSocket, is hard-coded for IPv4 which forces any gamer dev to either deal with Port Forwarding or port DMZ (where all ports are open). Winsock2, however, has been further developed and deals with both IPv4 and IPv6 which does not need port forwarding. On the downside, though, the Internet Service Providers (Cox, Verizon, Comcast, Google Fiber, etc.) who provide IPv6 don't implement it fully and end point to end point Reachability does not work for residential accounts. They want to force you to buy a business account and have an address plan like a corporation which is not what a directx gamer wants.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.