Thread: Winsock Messaging Program

  1. #1
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109

    Question Winsock Messaging Program

    I have tried several times to get winsock to work and my applications online, but to no avail. Recently, I started making a simple messaging program. For testing purpose, i tried to see if it would connect on my own computer, and it did. However, when I try to have a friend connect to me from over the internet, things get into a loop on my end (which is partially my fault for coding it that way), and quickly returns an error on the client end.

    Here is my code:
    Code:
    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    
    #define NETWORK_ERROR     -1
    #define NETWORK_OK         0
    #define ID_MESSAGELIST     100
    #define ID_MESSAGE         101
    #define ID_NICK            102
    #define ID_CONNECT         103
    #define ID_DISCONNECT      104
    #define ID_HOST            105
    #define ID_SEND            106
    
    void ReportError(int, const char *);
    
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    char szClassName[ ] = "MessengerTest";
    HWND hwnd, messagelist;
    WORD sockVersion;
    WSADATA wsaData;
    int iResult;
    SOCKET m_socket;
    SOCKET AcceptSocket;
    bool ishost;
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        MSG messages;
        WNDCLASSEX wincl;
    
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;
        wincl.style = CS_DBLCLKS;
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;
        wincl.cbClsExtra = 0;
        wincl.cbWndExtra = 0;
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        if (!RegisterClassEx (&wincl))
            return 0;
    
        hwnd = CreateWindowEx (
               0,
               szClassName,
               "Messenger Test",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT,
               CW_USEDEFAULT,
               544,
               375,
               HWND_DESKTOP,
               NULL,
               hThisInstance,
               NULL
               );
    
        ShowWindow (hwnd, nFunsterStil);
    
        while (GetMessage (&messages, NULL, 0, 0))
        {
            TranslateMessage(&messages);
            DispatchMessage(&messages);
        }
    
        return messages.wParam;
    }
    
    
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HDC hdc;
        PAINTSTRUCT ps;
        LPSTR szMessage = "Messages:";
        LPSTR szMessage2 = "Your Nickname:";
        LPSTR szMessage3 = "Enter a Message Here:";
        LPSTR szMessage4 = "Winsock Test: A Messaging Program";
        switch (message)
        {
            case WM_PAINT:
                 hdc = BeginPaint(hwnd, &ps);
                 SetBkColor(hdc, 0x007500);
                 TextOut(hdc, 16, 256, szMessage, strlen(szMessage));
                 TextOut(hdc, 16, 150, szMessage2, strlen(szMessage2));
                 TextOut(hdc, 16, 200, szMessage3, strlen(szMessage3));
                 TextOut(hdc, 16, 16, szMessage4, strlen(szMessage4));
                 EndPaint(hwnd, &ps);
                 break;
            case WM_CREATE:
                CreateWindow("Button", "Host", WS_BORDER | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 248, 48, 100, 30, hwnd, (HMENU) ID_HOST, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                CreateWindow("Button", "Send", WS_BORDER | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 160, 151, 100, 30, hwnd, (HMENU) ID_SEND, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                CreateWindow("Button", "Connect", WS_BORDER | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 16, 48, 100, 30, hwnd, (HMENU) ID_CONNECT, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                CreateWindow("Button", "Disconnect", WS_BORDER | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 132, 48, 100, 30, hwnd, (HMENU) ID_DISCONNECT, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                CreateWindow("Edit", "", WS_BORDER | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 16, 166, 80, 16, hwnd, (HMENU) ID_NICK, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                CreateWindow("Edit", "", WS_BORDER | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 16, 216, 506, 16, hwnd, (HMENU) ID_MESSAGE, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                messagelist = CreateWindow("Listbox", "", WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_BORDER | LBS_HASSTRINGS, 16, 272, 506, 60, hwnd, (HMENU) ID_MESSAGELIST, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Program Started...");
                break;
            case WM_COMMAND:
                 switch(LOWORD(wParam)) {
                     case ID_SEND:
                          break;
                     case ID_HOST:
                          iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
                          if ( iResult != NO_ERROR ) {
                              MessageBox(hwnd, "Error initializing Winsock!", "Error!", MB_ICONSTOP | MB_OK);
                              exit(0);
                          }
                          m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
                          if ( m_socket == INVALID_SOCKET ) {
                             MessageBox(hwnd, "Error at socket():", "Error!", MB_ICONSTOP | MB_OK);
                             MessageBox(hwnd, _itoa(WSAGetLastError(), NULL, 10), "Error!", MB_ICONSTOP | MB_OK);
                             WSACleanup();
                             exit(0);
                          }
                          sockaddr_in service;
                          service.sin_family = AF_INET;
                          service.sin_addr.s_addr = INADDR_ANY;
                          service.sin_port = htons( 27015 );
                          if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
                              MessageBox(hwnd, "bind() Failed!", "Error!", MB_ICONSTOP | MB_OK);
                              closesocket(m_socket);
                              exit(0);
                          }
                          SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Created Host");
                          SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Waiting for a Connection...");
                          if ( listen( m_socket, 1 ) == SOCKET_ERROR ) {
                              MessageBox(hwnd, "Error listening on socket!", "Error!", MB_ICONSTOP | MB_OK);
                              exit(0);
                          }
                          while (1) {
                                AcceptSocket = SOCKET_ERROR;
                                while (AcceptSocket == SOCKET_ERROR) {
                                      AcceptSocket = accept( m_socket, NULL, NULL );
                                }
                                SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Client Connected!");
                                m_socket = AcceptSocket; 
                                break;
                          }
                          ishost = true;
                          break;
                     case ID_CONNECT:
                          iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
                          if ( iResult != NO_ERROR ) {
                               MessageBox(hwnd, "Error initializing Winsock!", "Error!", MB_ICONSTOP | MB_OK);
                               exit(0);
                          }
                          m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
                          if ( m_socket == INVALID_SOCKET ) {
                              MessageBox(hwnd, "Error at socket():", "Error!", MB_ICONSTOP | MB_OK);
                              MessageBox(hwnd, _itoa(WSAGetLastError(), NULL, 10), "Error!", MB_ICONSTOP | MB_OK);
                              WSACleanup();
                              exit(0);
                          }
                          sockaddr_in clientService;
                          clientService.sin_family = AF_INET;
                          clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
                          clientService.sin_port = htons( 27015 );
                          SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Connecting...");
                          if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
                              MessageBox(hwnd, "Failed to connect.", "Error!", MB_ICONSTOP | MB_OK);
                              WSACleanup();
                              exit(0);
                          }
                          SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Connected to Host!");
                          break;
                     case ID_DISCONNECT:
                          closesocket(m_socket);
    	                  closesocket(AcceptSocket);
                          break;
                 }
                 break;
            case WM_DESTROY:
                 closesocket(m_socket);
    	         closesocket(AcceptSocket);
                 PostQuitMessage (0);
                 break;
            default:
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    I know that the send function doesnt work, I havent tried to fix it becuase i cant really test it.

    Another thing is that when you click the host button for instance, I tell the messages box to say that you have completed making a host, waiting for client to connect, etc. However, it doesnt disply these messages untill after a connection. is this becuase it has to wait to go through the message loop again to process it?

    Could it be my firewall, if the code is alright? I have Mcafee, but it also didnt work on a friend of mine's computer and he has a different firewall.


    This is really bugging me. Much of the winsock part of the code came directly or indirectly from online tutorials, wo I do not understand why it is failing me.

    All help is very much appreciated. Thanks in advance .

    I am using Dev-C++ 4.9.9.2, and like I said I have Mcafee for a firewall.
    Sic vis pacum para bellum. If you want peace, prepare for war.

  2. #2
    Politics&Cpp geek Da-Nuka's Avatar
    Join Date
    Oct 2004
    Posts
    104
    I had the same problem. (Atleast my code was okay, and it worked in a LAN).
    If you have the chance, try your program in a LAN, without firewalls and other protective programs.

    Over internett, there are several things which may disturb your program, for example firewalls, hardware-firewalls(on your connection/router/host), and most important: ROUTERS.
    If you are not connected directly to the internett, you also have to setup your router to forward the ports you want to use.

    On internett, you can allways connect from the innside to outside,
    but inncomming connections from the outside are a HUGE problem.

    How do messaging services like MSN fix this problem?
    I think they simply use a SERVER, which everyone connects to, and then avoid the problem.

    So if you want to test your program, i would reccomend to test on a local LAN without firewalls, or ANY other protective program or configurations.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Another thing is that when you click the host button for instance, I tell the messages box to say that you have completed making a host, waiting for client to connect, etc. However, it doesnt disply these messages untill after a connection. is this becuase it has to wait to go through the message loop again to process it?
    yes.
    It isn't a good Idea to use functions that take time (like accept called on a blocking socket) in a window procedure, this will make your pgram unresponsive.
    You should use at least another thread and have your thread send messages to your main window which can display the status messages to the user.
    Last edited by Quantum1024; 04-22-2005 at 04:08 AM.

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Code:
    while (1) {
       AcceptSocket = SOCKET_ERROR;
       while (AcceptSocket == SOCKET_ERROR) {
          AcceptSocket = accept( m_socket, NULL, NULL );
       }
       SendMessage(messagelist, LB_ADDSTRING, 0, (LPARAM) "Client Connected!");
       m_socket = AcceptSocket; 
       break;
    }
    First of all, it is a very bad idea to put an endless loop in the same thread as your UI. This should be done on a different thread, or with asynchronous sockets.

    Second, the reason your friend cant connect to you is probably because you are behind a firewall or a router (as others have mentioned). Therefore, you just stay suck in that endless loop, and your program appears frozen. You are binding to port 27015, so you need to forward that port on your router, and open it up in your firewall.

  5. #5
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    I took everything you all said into account. I fixed the program so that it used a thread to accept connections, which I should have done in the first place. The messages are all sent now fine. I opened port 27015 on my computer, and will test tomorrow to see if it now works.

    if it doesnt work, i will test on a LAN.

    If big games use servers, how do they get around having to send out info? Do thay have client query the server for the info? If so, how would that work?
    Last edited by Morgul; 04-22-2005 at 09:43 PM. Reason: Messages
    Sic vis pacum para bellum. If you want peace, prepare for war.

  6. #6
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    If big games use servers, how do they get around having to send out info? Do thay have client query the server for the info? If so, how would that work?
    Once a TCP connection has been established, there is nothing that keeps the server from sending the client arbitrary data at arbitrary times.

  7. #7
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    Oh ok I should have realized that.


    One last thing. Say I am writing a server for a game. I know that when one person connects, they get bound to a socket. When I want multiple ppl to connect, they would all get bound to the same socket right? Then, when I send info to a socket, they would all get that info? I wouldn't have to go through a list of connections or something?
    Sic vis pacum para bellum. If you want peace, prepare for war.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Quote Originally Posted by Morgul
    Oh ok I should have realized that.
    One last thing. Say I am writing a server for a game. I know that when one person connects, they get bound to a socket. When I want multiple ppl to connect, they would all get bound to the same socket right?
    No, each time you accept a new connection accept returns a new socket and the socket you passed to accept keeps listening. If you wanted all sockets to receive you would have to send that data to each socket.

  9. #9
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    So I'd want to make an array of sockets. Alright.



    Thanks for all your help everyone. I haven't tested it yet but I am pretty sure it will work. I am going to test it now, I'll post if it works or doesn't.
    Sic vis pacum para bellum. If you want peace, prepare for war.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Quote Originally Posted by Morgul
    So I'd want to make an array of sockets. Alright.
    .
    That's one appraoch another is to pass the socket handle to a newly created thread. If you're going to have an array of sockets then you will probably want to set them to none-blocking mode otherwise a recv operation could block on a socket and the others will be left waiting.

  11. #11
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    Yah nonblocking mode is a definite. I didnt test it becuase i was busy hooking up my new lan, but i will tomorrow morning.


    You guys have all been a great help. I thank you for everything you have done.
    Sic vis pacum para bellum. If you want peace, prepare for war.

  12. #12
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    If i am doing this:

    Code:
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    wouldn't that connect to myself? Don't I need to change that to whatever the ipaddress is of whoever I am connecting to? That is my problem isn't it?
    Sic vis pacum para bellum. If you want peace, prepare for war.

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    yes, 127.0.0.1 is your local computer. Set it to the IP you want to connect to or set it from user input giving the user the choice of what to connect to.

  14. #14
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    That is why it wasn't working. Thanks.
    Sic vis pacum para bellum. If you want peace, prepare for war.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can someome help me with a program please?
    By WinterInChicago in forum C++ Programming
    Replies: 3
    Last Post: 09-21-2006, 10:58 PM
  2. Need help with my program...
    By Noah in forum C Programming
    Replies: 2
    Last Post: 03-11-2006, 07:49 PM
  3. my server program auto shut down
    By hanhao in forum Networking/Device Communication
    Replies: 1
    Last Post: 03-13-2004, 10:49 PM
  4. Replies: 2
    Last Post: 05-10-2002, 04:16 PM
  5. Possible Networking Program Design :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 3
    Last Post: 05-04-2002, 06:20 PM