?
Solved

Winsock: how to close socket and send string to server

Posted on 2004-11-30
4
Medium Priority
?
376 Views
Last Modified: 2013-11-20
Hello, i've been trying winsock for a few days now. I've learned some stuff from websites, rewrote some small parts of the code for my own needs. But i've got 2 problems now. 1st is i cant close the listening socket. I know the code, but i have 1 button to make the sock start and in a 2nd button i want it to make it close the socket. But it doesnt seem to work if i place the closesocket under another function. The 2nd one is sending a string to a server. Here is the code i use for my client. Hope it isnt to messy and that someone can help me out. If i wasnt clear about something please tell me and ill try to explain better.


-----------------------------------------

#include <windows.h>
#include <winsock.h>

#pragma comment(lib,"ws2_32.lib")

const char g_szClassName[] = "Class";

HWND cmdConnect;
HWND cmdDisconnect;
HWND cmdSendMSG;

#define IDB_BUTTON 100
#define IDB_BUTTON1 101
#define IDB_BUTTON2 102


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
      switch(msg)
      {
      case WM_CREATE:
            cmdConnect = CreateWindowEx(0,"BUTTON","Connect",WS_VISIBLE | WS_CHILD,10,20,80,20,hwnd,(HMENU) IDB_BUTTON,((LPCREATESTRUCT)lParam)->hInstance,NULL);
            cmdDisconnect = CreateWindowEx(0, "BUTTON", "Disconnect", WS_VISIBLE | WS_CHILD,90,20,80,20,hwnd,(HMENU) IDB_BUTTON1, ((LPCREATESTRUCT)lParam)->hInstance,NULL);
            cmdSendMSG = CreateWindowEx(0,"BUTTON","Send a MessageBox", WS_VISIBLE | WS_CHILD, 15,50,150,20,hwnd,(HMENU) IDB_BUTTON2, ((LPCREATESTRUCT)lParam)->hInstance,NULL);
            break;
      case WM_COMMAND:
      switch(wParam)
      {
      case IDB_BUTTON: // ***cmdConnect***
            //MessageBox(NULL,"The connecting part here?","Dunno", MB_OK);
            WSADATA wsaDat;
            
            if(WSAStartup(MAKEWORD(2,2),&wsaDat) != 0)
            {
                  MessageBox(NULL,"Could not start winsock","ERROR",MB_ICONWARNING | MB_OK);
                  return 0;
            }

            SOCKET sock;
            sock = socket(AF_INET,SOCK_STREAM,0);

            if(sock==INVALID_SOCKET)
            {
                  //if host isnt found
                  MessageBox(NULL,"Winsock could not connect","ERROR",MB_ICONEXCLAMATION | MB_OK);
                  return 0;
            }

            SOCKADDR_IN SockAddr;
            SockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
            SockAddr.sin_family = AF_INET;
            SockAddr.sin_port = htons(1234);
            
            if(connect(sock,(SOCKADDR *)(&SockAddr),sizeof(SockAddr))==SOCKET_ERROR)
            {
                  MessageBox(NULL,"Winsock could not connect to the host","ERROR",MB_ICONWARNING | MB_OK);
                  return 0;
            }
            MessageBox(NULL,"You are connected!","Client",MB_ICONINFORMATION | MB_OK);
            
            break;
      case IDB_BUTTON1: // ***cmdDisconnect***

            break;
      case IDB_BUTTON2: // ***cmdSendMSG***

            break;
      }
      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 nCmdShow)
{
      WNDCLASSEX wc;
      HWND hwnd;
      MSG Msg;

      wc.cbClsExtra = 0;
      wc.cbSize = sizeof(WNDCLASSEX);
      wc.cbWndExtra = 0;
      wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
      wc.hCursor = LoadCursor(NULL,IDC_ARROW);
      wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
      wc.hInstance = hInstance;
      wc.lpfnWndProc =  WndProc;
      wc.lpszClassName = g_szClassName;
      wc.lpszMenuName = NULL;
      wc.style = 0;

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

    hwnd = CreateWindowEx(
        0,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

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

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

-----------------------------------
0
Comment
Question by:OutlawZ
  • 2
  • 2
4 Comments
 
LVL 19

Expert Comment

by:drichards
ID: 12713686
You don't show any code for you rlistening socket, so it's hard to say what might be wrong.

In the code you do have, you have the problem that your socket is a local non-static variable, so once you get connected, you lose the handle to the socket and you cannot perform any more operations on it.  This may be your problem in trying to close your socket as well.  You need to store the socket somewhere that you will have access to it across invocations of WndProc.  You can make it global or static as a quick fix.

Then, to send data, use "send":

    send(sock, buf, bufLen, 0);

where sock is your socket, buf is a pointer to a string of chars (like 'char buf[1024];' or 'char *buf = new char[1024];'), bufLen is the number of data bytes pointed to by buf (may not be full length of array), and 0 is a flag parameter.

You can use 'WSAAsyncSelect' to set up a message that will be posted when there is data to receive.  Something like:

    WSAAsyncSelect(sock, hWnd, wMsg, FD_READ); // wMsg is the message ID that gets posted.  Add a case for it in WndProc.


Then you call "recv" in your message handler:

    recv(sock, buf, bufLen, 0);

In this case bufLen IS the size of the array that you pass in.  The return value of "recv" is the number of bytes actually received.
0
 

Author Comment

by:OutlawZ
ID: 12718903
Im still trying to not lose the handle of the sock, so i tried to put it in a header file. Here is the full source of the client and server. What i havent figured out yet is how to close the socket, or do i loose the handle this way too?? Hope you or anyone else can help me out with this.

The client - main.cpp

#include <windows.h>
#include <winsock.h>

#include "sock1.h"

#pragma comment(lib,"ws2_32.lib")

const char g_szClassName[] = "Class";

HWND cmdConnect;
HWND cmdDisconnect;
HWND cmdSendMSG;

#define IDB_BUTTON 100
#define IDB_BUTTON1 101
#define IDB_BUTTON2 102


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
      switch(msg)
      {
      case WM_CREATE:
            cmdConnect = CreateWindowEx(0,"BUTTON","Connect",WS_VISIBLE | WS_CHILD,10,20,80,20,hwnd,(HMENU) IDB_BUTTON,((LPCREATESTRUCT)lParam)->hInstance,NULL);
            cmdDisconnect = CreateWindowEx(0, "BUTTON", "Disconnect", WS_VISIBLE | WS_CHILD,90,20,80,20,hwnd,(HMENU) IDB_BUTTON1, ((LPCREATESTRUCT)lParam)->hInstance,NULL);
            cmdSendMSG = CreateWindowEx(0,"BUTTON","Send a MessageBox", WS_VISIBLE | WS_CHILD, 15,50,150,20,hwnd,(HMENU) IDB_BUTTON2, ((LPCREATESTRUCT)lParam)->hInstance,NULL);
            break;
      case WM_COMMAND:
      switch(wParam)
      {
      case IDB_BUTTON: // ***cmdConnect***
            //MessageBox(NULL,"The connecting part here?","Dunno", MB_OK);
            Sock_Connect();
            break;
      case IDB_BUTTON1: // ***cmdDisconnect***

            break;
      case IDB_BUTTON2: // ***cmdSendMSG***

            break;
      }
      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 nCmdShow)
{
      WNDCLASSEX wc;
      HWND hwnd;
      MSG Msg;

      wc.cbClsExtra = 0;
      wc.cbSize = sizeof(WNDCLASSEX);
      wc.cbWndExtra = 0;
      wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
      wc.hCursor = LoadCursor(NULL,IDC_ARROW);
      wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
      wc.hInstance = hInstance;
      wc.lpfnWndProc =  WndProc;
      wc.lpszClassName = g_szClassName;
      wc.lpszMenuName = NULL;
      wc.style = 0;

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

    hwnd = CreateWindowEx(
        0,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

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

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

Client - sock1.h

#define NETWORK_OK 1
int Sock_Connect();

int Sock_Connect()
{
                  WSADATA wsaDat;
            
            //handle WSADATA for errors
            if(WSAStartup(MAKEWORD(2,2),&wsaDat) != 0)
            {
                  MessageBox(NULL,"Could not start winsock","ERROR",MB_ICONWARNING | MB_OK);
                  return 0;
            }

            SOCKET sock;
            sock = socket(AF_INET,SOCK_STREAM,0);

            //error handling for SOCKET
            if(sock==INVALID_SOCKET)
            {
                  //if host isnt found
                  MessageBox(NULL,"Winsock could not connect","ERROR",MB_ICONEXCLAMATION | MB_OK);
                  return 0;
            }

            SOCKADDR_IN SockAddr;
            SockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
            SockAddr.sin_family = AF_INET;
            SockAddr.sin_port = htons(1234);
            
            if(connect(sock,(SOCKADDR *)(&SockAddr),sizeof(SockAddr))==SOCKET_ERROR)
            {
                  MessageBox(NULL,"Winsock could not connect to the host","ERROR",MB_ICONWARNING | MB_OK);
                  return 0;
            }
            MessageBox(NULL,"You are connected!","Client",MB_ICONINFORMATION | MB_OK);

            //***This closes the server?***
//            closesocket(sock);
//            WSACleanup();

            return NETWORK_OK;
}

-----------------------------------

Server - main.cpp

#include <windows.h> // include junk, make sure mpr.lib and wsock32.lib are included
#include <winsock.h>

#pragma comment(lib,"ws2_32.lib")

#define NETWORK_OK 0

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

{
WSADATA WsaDat; // WsaDat Variable
WSAStartup(MAKEWORD(1,1), &WsaDat); // Startup Winsock 1.1
SOCKET Socket = socket(AF_INET, SOCK_STREAM, 0); // Setup Socket
SOCKADDR_IN SockAddr; // Sockaddr_in variable

SockAddr.sin_port = htons(1234); // Port to listen on is 50
SockAddr.sin_family = AF_INET; // AF_INET
SockAddr.sin_addr.S_un.S_addr = INADDR_ANY; // Listen on any address

bind(Socket, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)); // Bind socket to port

listen(Socket, 1); // Set that socket to listening for a connection

SOCKET TempSock = SOCKET_ERROR;
// The accept function below returns a working socket if a connection was revieved,
// but if not, then it returns socket_error, so we need a temporary socket for now

while (TempSock == SOCKET_ERROR) // Keep waiting for connection until we get one, no errors
{
TempSock = accept(Socket, NULL, NULL); // Try to accept a connection
} // Go back if recv returned SOCKET_ERROR

Socket = TempSock; // accept() returned a good socket if it was successful, so make Socket equal that.

int RetVal = SOCKET_ERROR; // recv() also returns SOCKET_ERROR if nothing was recieved, nother temp
char String[50]; // Variable to  hold what we recieved

while (RetVal == SOCKET_ERROR) // Keep recieving until we get something not SOCKET_ERROR
{
RetVal = recv(Socket, String, 50, 0); // Try to recieve something, SOCKET_ERROR if nothing is there
} // If nothing was there, loop back and try again.

// char String now holds the data that was sent from some random computer
// no error checking at all here, so much can go wrong.
return NETWORK_OK;
}#include <windows.h> // include junk, make sure mpr.lib and wsock32.lib are included
#include <winsock.h>

#pragma comment(lib,"ws2_32.lib")

#define NETWORK_OK 0

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

{
WSADATA WsaDat; // WsaDat Variable
WSAStartup(MAKEWORD(1,1), &WsaDat); // Startup Winsock 1.1
SOCKET Socket = socket(AF_INET, SOCK_STREAM, 0); // Setup Socket
SOCKADDR_IN SockAddr; // Sockaddr_in variable

SockAddr.sin_port = htons(1234); // Port to listen on is 50
SockAddr.sin_family = AF_INET; // AF_INET
SockAddr.sin_addr.S_un.S_addr = INADDR_ANY; // Listen on any address

bind(Socket, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)); // Bind socket to port

listen(Socket, 1); // Set that socket to listening for a connection

SOCKET TempSock = SOCKET_ERROR;
// The accept function below returns a working socket if a connection was revieved,
// but if not, then it returns socket_error, so we need a temporary socket for now

while (TempSock == SOCKET_ERROR) // Keep waiting for connection until we get one, no errors
{
TempSock = accept(Socket, NULL, NULL); // Try to accept a connection
} // Go back if recv returned SOCKET_ERROR

Socket = TempSock; // accept() returned a good socket if it was successful, so make Socket equal that.

int RetVal = SOCKET_ERROR; // recv() also returns SOCKET_ERROR if nothing was recieved, nother temp
char String[50]; // Variable to  hold what we recieved

while (RetVal == SOCKET_ERROR) // Keep recieving until we get something not SOCKET_ERROR
{
RetVal = recv(Socket, String, 50, 0); // Try to recieve something, SOCKET_ERROR if nothing is there
} // If nothing was there, loop back and try again.

// char String now holds the data that was sent from some random computer
// no error checking at all here, so much can go wrong.
return NETWORK_OK;
}
0
 
LVL 19

Accepted Solution

by:
drichards earned 800 total points
ID: 12723343
You still have the socket as a local non-static variable which means that as soon as the function (Sock_Connect or WinMain) exits, the socket is lost.  These locals are pushed onto the stck when the function executes and poped off after it finishes.  They are created new on every pass and old values are lost.

In each case the easiest thing is to make the socket a global variable.  Put it right after any #include statements before any functions and define it like:

SOCKET  sock;  // or 'SOCKET TempSock;' in the server case.

If you want to use it in another cpp, add a line "extern SOCKET sock;' in the other cpp.

That will work as a first cut.  If you're going to be doing multiple connections, this will probably not suffice.
0
 

Author Comment

by:OutlawZ
ID: 12728247
Thanks, i tried like you said and it worked. I used a header file to make the SOCK and WSADATA global and i have a function in it that handles the connecting and closing of the sock.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses
Course of the Month15 days, 22 hours left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question