Jump to content

Server using windows.h and Winsock

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
5 replies to this topic

#1
telboon

telboon

    Newbie

  • Members
  • PipPip
  • 26 posts
I've made a server that allows simultaneous chat with many users. It's not really practical, but I'm using this to test out what I've learnt online. Just started to learn network prorgramming yesterday.

However, there's a problem. When there's no user connected, it shows that user is connected.

Init Successful!

Socked Initialised!

Binding successful!

Socket 0 used!

User Connected on thread: 0

Socket 1 used!

Socket 2 used!

Socket 3 used!

Socket 4 used!

Socket 5 used!

Socket 6 used!

Socket 7 used!

Socket 8 used!

Socket 9 used!

When a user has connected, and established connection, it doesn't say connection established, until another connection starts.

Init Successful!

Socked Initialised!

Binding successful!

Socket 0 used!

User Connected on thread: 0

Socket 1 used!

Socket 2 used!

Socket 3 used!

Socket 4 used!

Socket 5 used!

Socket 6 used!

Socket 7 used!

Socket 8 used!

Socket 9 used!

User Connected on thread: 0

User Connected on thread: 8


What is wrong with my code?
#include <windows.h>

#include <iostream>

using namespace std;


#define MAX_THREAD 10

#define PORT 80


void cReinit(char [],int); //Reinit string

DWORD WINAPI rec(LPVOID ); //Have 10 sockets to allow simultaneous connections


class Data //Shared Data

{

    public:

        SOCKET kSock; //Listening Socket

        SOCKET aSock[MAX_THREAD]; //Accepted Sockets

        char buf[256]; 

        bool check[MAX_THREAD]; //Check if socket used. For functions to identify sockets

        bool onoff; //Prevent clashes of the threads in case many accepts at 1 time

        sockaddr_in sin; 

};


int main()

{

    HANDLE hThread[MAX_THREAD]; //makes thread and ids

    DWORD dThreadID[MAX_THREAD];

    WSAData wsdata;

    WORD sver=MAKEWORD(2,0);

    int nret=WSAStartup(sver,&wsdata); //starting up

    if (nret!=0)

    {

        cout<<"Startup Failed.\n";

        WSACleanup();

        system("PAUSE");

        return -1;

    }

    cout<<"Init Successful!\n";

    Data dat;

    dat.onoff=0;

    dat.kSock=socket(AF_INET, SOCK_STREAM, 0); //makes a tcp socket

    if (dat.kSock==INVALID_SOCKET)

    {

        cout<<"Socket failed to initialised.\n";

        WSACleanup();

        system("PAUSE");

        return -1;

    }

    cout<<"Socked Initialised!\n";

    dat.sin.sin_port=htons(PORT);

    dat.sin.sin_addr.s_addr=INADDR_ANY;

    dat.sin.sin_family=AF_INET;

    if (bind(dat.kSock,(sockaddr*)&dat.sin,sizeof(dat.sin))==SOCKET_ERROR)

    {

        cout<<"Failed to bind.\n";

        WSACleanup();

        system("PAUSE");

        return -1;

    }

    cout<<"Binding successful!\n";

    dat.onoff=0;

    for (int i=0;i<MAX_THREAD;i++) //starting the 10 threads

    {

        Sleep(100); //sleep to prevent clashes

        dat.check[i]=0;

        hThread[i]=CreateThread(

            NULL,

            0,

            rec,

            &dat,

            0,

            &dThreadID[i]);

        if (hThread[i]==0)

        {

            cout<<"Error on Thread: "<<i<<endl;

        }

    }

    char buff[256]="";

    while (1) //sending out

    {

        cReinit(buff,256);

        cin.getline(buff,256);

        strcat(buff,"\n");

        for (int i=0;i<MAX_THREAD;i++)

        {

            if (dat.check[i]==1)

            {

                send(dat.aSock[i], buff, sizeof(buff), 0);

            }

        }

    }

    WaitForMultipleObjects(10,hThread, TRUE, INFINITE);

    cout<<"Done.\n";

    WSACleanup();

    system("PAUSE");

    return 0;

}



DWORD WINAPI rec(LPVOID lpData)

{

    char buf[256]="";

    int len;

    Data *dat=(Data*) lpData;

    int num; //socket number

    for (int i=0;i<MAX_THREAD;i++) //Allocating Socket number

    {

        if (dat->check[i]==0) 

        {

            dat->check[i]=1;

            num=i;

            cout<<"Socket "<<i<<" used!\n";

            break;

        }

    }

    while (1)

    {

        while ((listen(dat->kSock, SOMAXCONN)==SOCKET_ERROR) || (dat->onoff==1)) //listening, with check to make sure threads don't clash

        {

            Sleep(100); //prevent high cpu

        }

        dat->onoff=1; //checked

        cout<<"User Connected on thread: "<<num<<endl;

        len=sizeof(dat->sin);

        dat->aSock[num]=accept(dat->kSock, (sockaddr*) &dat->sin, &len); //accepts conenction

        dat->onoff=0; //unchecked

        cout<<"Connection Establish on thread: "<<num<<endl;

        while (strcmp(buf,".")!=0) //keep on receiving

        {

            recv(dat->aSock[num], buf, sizeof(buf), 0);

            cout<<buf;

            cReinit(buf, 256);

        }

        closesocket(dat->aSock[num]);

        cout<<"Connection terminated on thread: "<<num<<endl;

    }

    return 0;

}


void cReinit(char cha[], int len) //to clear strings

{

    for (int i=0;i<len;i++) cha[i]=0;

}



#2
telboon

telboon

    Newbie

  • Members
  • PipPip
  • 26 posts
Also, this is my first time applying winsock, and threads. Is my code efficient or "proper"?

#3
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,713 posts
First of all, I'd suggest you declare Data as a struct, not a class. This won't even compile on my computer - what compiler are you using? You're also not protecting a shared resource with semaphores - a very bad thing to do. Read up on concurrency. When two threads try to access the same data at the same time, they'll corrupt the data and who knows what will happen; that's probably why your program doesn't work.

#4
telboon

telboon

    Newbie

  • Members
  • PipPip
  • 26 posts
I'm using Dev C++ compiiler. Previously I was using struct, but I thought struct was old, and was trying classes to see if it works. The struct and class have same result, but I guess i'll stick back with struct.

What are semaphores? I did look it up on google, but still, I couldn't understand it. Is it a function that is declared by the programmer or a in-built stuff?

However, I did have some variables to prevent clashes of the threads. So, it should not be a problem with threads clashing.

#5
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,713 posts
Access to the variables is not guaranteed to be atomic, so if you have a boolean called lock the thread setting it to true could very well be interrupted right in the middle of updating it, and then you'd have problems. The operating system guarantees that semaphores will be accessed atomically.

A semaphore is a sort of counter. When created by the parent thread, it is set to an initial value, say 10. Every time a thread calls WaitForSingleObject on the semaphore, the counter is decremented atomically, and the thread resumes execution. However, if the counter is 0, the thread is suspended. When the counter is incremented by another thread, the first thread is "woken up" and decrements the counter, then resumes execution. Semaphores can be used as locks around data by initializing them with a counter value of 1, so only 1 thread can access the data at a time. This is a very minimal example of the functions needed:

#include <windows.h>

int main(void)
{
    HANDLE hSem = CreateSemaphore(NULL,1,1,"lockData");
    int data;
    ...create threads...
    WaitForMultipleObjects(...wait for all threads to end...);
    CloseHandle(hSem);
}

DWORD ThreadProc(LPVOID *pdata)
{
    HANDLE hSemData = OpenSemaphore(SYNCHRONIZE,FALSE,"lockData");
    WaitForSingleObject(hSemData,INFINITE);
    ...do some stuff...
    ReleaseSemaphore(hSemData,1,NULL);
}

MSDN - Synchronization

#6
telboon

telboon

    Newbie

  • Members
  • PipPip
  • 26 posts
Oh.. Thanks for the tip! Will read up more about semaphore!:)