windows simple chat program

I'm working a program for class. We're supposed to write a chat program.

I was trying to figure out how to get multiple clients connected.

Could someone help me out by explaining how to get different ports and sockets or whatever rolling? I'm under the impression that you open up multiple sockets on one port correct?

Initially I thought I'd have it so one port accepted incoming connections, and then told each client to connect to a different port to do the rest of the communication stuff, but obviously that's a waste of ports and all and I don't need that.

So how do I set this up? One socket accepting connections and responding with new socket information for further communication?

How should I set this up though? If only one socket can accept incoming connections, then after the client connects to receive some new info about the socket it must create next, then the client would act as server and wait for a connection from the server (to solve the only one port accepting connections problem).

That might require some wierd address resolution stuff, Maybe I'm making this harder than it's supposed to be.
Last edited on
btw, i'm using winsock2.h
It's actually not that hard if you are just planning on using Telnet to do it...this tutorial should help you:

http://johnnie.jerrata.com/winsocktutorial/

Most of the functions are the same in winsock2.h as far as I know, but if you run into any problems, just ask.
Last edited on
Thanks for that great link!

Maybe you can help me understand it a bit more so I can expound on it for my own code.

That example has a few lines saying how many connections to accept:
nret = listen(listeningSocket, 10);

So one client connects and it says
theClient = accept(something);

So in that tutorial one client connects and whatever happens happens. In mine I need to get multiple clients. How should I do this? So far I've made a struct for each client, something like:

1
2
3
4
struct CLIENT{
	bool populated;
	char handle[20];
};


So I'm going to add a socket or something to that struct so that later if I want to send a message to someClient.handle I could use something like

1
2
3
if(client[p].handle == charBuf)
     send(client[p].socket, charMsg, len, 0);
)



oK so I think that all looks well and good, but I am not sure how to handle acceptance. etc.

As it is, I accept the client and send messages back and forth, but since it's all sequential and blocking I can't sit and accept clients while sending messages back and forth. Should I use threads to break this up now? and how if you don't mind my asking, in your opinion what would be the best way to go about that? Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
main{
   do some stuff, set up socket stuff etc...
   loop{
       wait for connection....
       upon connection spawn new thread for listen send
   }
}

threadFunc{
   while(connected){
      listen for messages
      depending on messages run corresponding func
   }
}



My problem is though, the client, they need to be able to receive messages while waiting to send messages. Damn I guess the client needs to have two threads running as well then? But while scanf on the client side is blocking can a seperate thread with printf print to the same stdout?
I am not at my code right now, but I'll help you based on what I remember.

Yes, I made the Client structs, but instead of making a bool populated, I made a vector of Clients and had the host thread iterate through it. I also had a vector of strings that the Client would input their commands into, and the host thread would look at the "top" command every revolution and interpret the command.

The way I handled acceptance is that I had another thread that simply waited for a connection, and when it got one, it spun off another thread of itself, and created a new Client thread for them, as well as push_back()'ing them into the vector of clients.

I had each client thread simply sit and wait for a message and they would put it into their command vector, which would allow the host to deal with it.

So basically I had:

Host Thread
Client Thread(s)
Accepter Thread

FYI: this means that the host has to connect to themselves using a client (you can just use localhost: whatever port you use).

Once I get home (probably an hour or two) I'll get my code and probably be able to explain it a lot better then the above...Since it will probably seem a little disjointed and confusing (to me anyway XD)
Last edited on
ya for now i was just going to use populated or check the handle for NULL instead of making something like a linked list to handle multiple clients, so just have an array of that struct instead of a linked list or whatever. populated would just mean that that client was not connected so the info could be overwritten. move that to something more worth while later.


I guess I'm kind of confused about how to make active sockets vs accepting sockets (or whatever they're called). I get it in theory, only one socket per port can accept incoming connections, but you have many active and connected sockets per port as well as the active one. Right? i just don't understand how to code that up i guess, the difference between accepting and active. Some code to that effect w/ multiple clients would be awesome.

Thank you lots for your help fire! I really appreciate it!
1.) Active sockets are pretty much made after you have accepted a connection (iirc)
2.) Yes, you are correct about the socket/active stuff

No problem. :)

The only thing I had a problem was with the using recv, which only gets one byte at a time...try making it first, and if you are still stuck I'll help.


Anyway, I defined my client(s) as this class:

1
2
3
4
class Client {
     SOCKET socket;
     vector <string> commands;
}


I had WinMain create two threads...an accepter/client thread and a host thread. The host thread iterated through the vector of Clients and checked the top entry in commands if it contained something. It would then interpet the command/send data etc as needed.

My accepter thread sat and waited for an incoming connection and then it started a loop that received data from the socket, as well as creating a copy of itself.

I think that is everything...if you need more help on the specifics, state where you are having a problem and I'll help you.
OK so here's what I'm thinking for the server side:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Client {
     SOCKET s;
     char handle[20];
     int recvThreadID;
}

void main(){

  //spawn menu / input gathering thread (so that everything can be shut
  //down from server side

  //Set up socket stuff

  //Spawn accepting clients thread

  //Wait for input thread to close, upon closing kill all client threads and then close

}

void accepting(){

  //Wait for a client to connect

  //Spawn new accepting thread

  //loop:
  // wait for messages from client untill connection closed
  // upon message run a particular function that may send messages back

  //if connection closed, delete client from list of clients and return ending the 
  //thread

}


This way on server side I can use the int recvThreadID for each client in an end threads function when closing program.

Just kind of sounding it out in my head, any comments on that plan of attack?
It looks good except for one question I had, how are you going to get the commands from the client?
after the 'accepting' thread gets a client connected, it sits and continuously receives messages from the client. each message will be a command.
Code for receiving messages:
1
2
3
         char buf[MAX_LINE];
         int len = recv( s, buf, MAX_LINE, 0 );
         buf[len] = 0;


client side have two threads:

1
2
3
4
5
6
void main(){
  //open thread for collecting input
  //open thread for accepting messages from server
  //when thread for collecting input terminates (user quit), kill
  //  thread for messages from server, close socket
}


I know there is a way to make it so scanf can sit and "blocK" but still letting printf print to same stdout. Do you know how to do that? If not I'll probably make a new thread since i think it's probably somewhat basic. Then as long as you know that only one thread will be taking input at a time, you'll be ok.
Hrm, I think I might have not explained it well enough to you...when you make threads and have people connect, you cannot use scanf() or anything like that. You must use recv() (recieves data from the socket), which is a blocking function...so it would be more complicated if you wanted to do it that way. I had my clients simply add their "commands" to their commands vector and had my host thread simply scan the tops of the commands vector. It would also ensure that each person would get at least one command per revolution. However, it does require that there be a unique identifier that each person has, which I simply used a name (when inputting the name it checked to see if it already was in the system). Also, you will have to use CriticalSections in order to prevent say, the host thread from trying to read the top part of the commands vector while the client thread is trying to add stuff.

If you want to keep going your direction, you would probably have to make a new thread that recieves for each one of your client threads (you could put that in your client thread after it recieves a connection) and then have the recieving thread put the data somewhere (perferably a vector of some sort, then you won't have to worry about out of bounds access). You could then have the host client use that data and send it to everyone.

I also noticed that you made your handle a char array, just make it of type HANDLE, it'll make it easier to read (and more correct IMO).
Last edited on
my handle is a char array, not like a sig handle or anything, its like the screen name of the client.

And when I was saying scanf was blocking, i mean on either client or server side there will be a scanf running to get input from the using from stdin. So the client types "send all Hello World" and hits enter, that gets put into a buffer and then sent with send to the server. Meanwhile yea you're right, the client has a seperate thread running recv to pick up messages from the server.

Ah, gotcha. You could probably just make that a string (unless you specifically have to use a char array).

Unfourtanely, you cannot run scanf() or printf() on sockets. These are made to send directly to the console window (the "host" window) and recieve from there. You would have to use send() and recv() in order to get anything from the socket.
nono i know that scanf/printf don't go to the sockets. I'm saying that say on the client side, scanf sits and blocks on an input thread so that it catches what the clients types. meanwhile recv is blocking in another thread waiting for messages from the server. when a message from the server comes, it is processed and eventually something is printed to the clients' screen with printf, all the while scanf is still waiting for the client to type something.

i just needed to be sure that even if scanf was blocking waiting for input on std that printf could still print to std, which when you split the program up into different threads it works fine. i'll post my code when i'm all done. meanwhile i have another question:
here's what examples online and everything are saying to do for the socket stuff:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    // Initialize Winsock.
      WSADATA wsaData;
      int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
      if ( iResult != NO_ERROR ){
         printf("Error at WSAStartup()\n");
         return;
      }
   
    // Create a socket.
      SOCKET controlSocket;
      controlSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
   
      if ( controlSocket == INVALID_SOCKET ) {
         printf( "Error at socket(): %ld\n", WSAGetLastError() );
         WSACleanup();
         return;
      }
   
    // Bind the socket.
      sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = INADDR_ANY; //use local address
      addr.sin_port = htons(SERVER_PORT);
      if ( bind( controlSocket, (SOCKADDR*) &addr, sizeof(addr) ) == SOCKET_ERROR ) {
         printf( "bind() failed.\n" );
         closesocket(controlSocket);
         WSACleanup();
         return;
      }
   
    // Listen on the Socket.
      if ( listen( controlSocket, MAX_PENDING ) == SOCKET_ERROR ){
         printf( "Error listening on socket.\n");
         closesocket(controlSocket);
         WSACleanup();
         return;
      }
   
    // Accept connections.
      SOCKET s;
   
      printf( "Waiting for a client to connect...\n" );
      while(1){
         s = accept( controlSocket, NULL, NULL );
         if( s == SOCKET_ERROR){
            printf("accept() error \n");
            closesocket(controlSocket);
            WSACleanup();
            return;
         }
      
         printf( "Client Connected.\n");
      
      	// Send and receive data.
         char buf[MAX_LINE];
         int len = recv( s, buf, MAX_LINE, 0 );
         buf[len] = 0;
		 
		 
         int p = newClient(clientList,buf);
		 if(p>-1){
			send( s, clientList[p].handle, strlen(clientList[p].handle), 0 );
			}
		 else{
			 char *reject = "Too many clients connected at this time or there was an error! Sorry!";
			 send( s, reject, strlen(reject), 0);
		 }
			 
         closesocket(s);


ok that's all well and good, but i'm trying to figure out how to split it up so that my 'accepting' thread is separate. Should I make my 'accepting' thread something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
SOCKET s;
   
      printf( "Waiting for a client to connect...\n" );
      while(1){
         s = accept( controlSocket, NULL, NULL );
         if( s == SOCKET_ERROR){
            printf("accept() error \n");
            closesocket(controlSocket);
            WSACleanup();
            return;
         }
      
         printf( "Client Connected.\n");
      //
     //  THIS IS WHERE THIS ACCEPTING THREAD SPAWNS A COPY OF ITSELF
     //

      	// Send and receive data.
         char buf[MAX_LINE];
         int len = recv( s, buf, MAX_LINE, 0 );
         buf[len] = 0;
		 
		 
         int p = newClient(clientList,buf);
		 if(p>-1){
			send( s, clientList[p].handle, strlen(clientList[p].handle), 0 );
			}
		 else{
			 char *reject = "Too many clients connected at this time or there was an error! Sorry!";
			 send( s, reject, strlen(reject), 0);
		 }
			 
         closesocket(s);
         printf( "Client Closed.\n");
      }


Or do I need to go through more of the set up stuff each time i want to start accepting connections? (i need to have multiple connections)
You would do it like this:

1
2
3
4
5
6
7
8
9
main { //<-- WinMain(......)
     //start up winsock etc
     HANDLE host = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) HostThreadFunction, NULL, 0, NULL);
     CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) AccepterThreadFunction, NULL, 0, NULL);
     while(host != NULL) {
          Sleep(50);
     }
     return 0;
}


This will start the threads and then have this thread basically idle until the host thread shuts down. Assuming you are using the names as above, define your other functions as:

1
2
3
4
5
6
7
8
9
10
WINAPI HostThreadFunction(void) {
     //respond to commands, etc
}

WINAPI AccepterThreadFunction(void) {
     //wait for connection
     //insert self into array, set up client, etc
     CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) AccepterThreadFunction, NULL, 0, NULL);
     //recieve commands, etc
}


With this set up, you won't have to worry about a maximum number of connections. Well, you will, but I doubt you will get to the point where it starts straining the computer.
Last edited on
Topic archived. No new replies allowed.