GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 20-Oct-2006, 10:50
Justin Fox Justin Fox is offline
Junior Member
 
Join Date: Sep 2006
Posts: 46
Justin Fox is on a distinguished road

server/client.... multiple clients


ok, I'm supposed to make a server/client program that accepts
connections from clients, but allows them to chat to each other...

now in java, all you have to do is just send a message to the server,
and the server just echos that messages to all the clients...

but in C, once you call the accept message, the thread pauses, and waits
for a connection...

what i need to know, is how to create another thread in C to be able
to handle message I/O from client to client..

Thanks for the help..

Justin


here is the code..

CPP / C++ / C Code:
/* chatserver.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);

/*-----------------------------------------------------------------------
 *
 * Program: chatserver
 * Purpose: wait for a connection from a chatclient & allow users to chat
 * Usage:   chatserver <appnum>
 *
 *-----------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	connection	conn;
	int		len;
	char		buff[BUFFSIZE];

	if (argc != 2) {
		(void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);
		exit(1);
	}

	(void) printf("Chat Server Waiting For Connection.\n");

	/* wait for a connection from a chatclient */

	conn = await_contact((appnum) atoi(argv[1]));
	if (conn < 0)
		exit(1);
	
	(void) printf("Chat Connection Established.\n");
	
	/* iterate, reading from the client and the local user */

	while((len = recvln(conn, buff, BUFFSIZE)) > 0) {
		(void) printf(RECEIVED_PROMPT);
		(void) fflush(stdout);
		(void) write(STDOUT_FILENO, buff, len);
		
		/* send a line to the chatclient */

		(void) printf(INPUT_PROMPT);
		(void) fflush(stdout);
		if ((len = readln(buff, BUFFSIZE)) < 1)
			break;
		buff[len - 1] = '\n';
		(void) send(conn, buff, len, 0);
	}

	/* iteration ends when EOF found on stdin or chat connection */

	(void) send_eof(conn);
	(void) printf("\nChat Connection Closed.\n\n");
	return 0;
}



CPP / C++ / C Code:
/* chatclient.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);

/*-----------------------------------------------------------------------
 *
 * Program: chatclient
 * Purpose: contact a chatserver and allow users to chat
 * Usage:   chatclient <compname> <appnum>
 *
 *-----------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	computer	comp;
	connection	conn;
	char		buff[BUFFSIZE];
	int		len;

	if (argc != 3) {
		(void) fprintf(stderr, "usage: %s <compname> <appnum>\n",
			       argv[0]);
		exit(1);
	}

	/* convert the compname to binary form comp */

	comp = cname_to_comp(argv[1]);
	if (comp == -1)
		exit(1);

	/* make a connection to the chatserver */

	conn = make_contact(comp, (appnum) atoi(argv[2]));
	if (conn < 0) 
		exit(1);

	(void) printf("Chat Connection Established.\n");
	(void) printf(INPUT_PROMPT);
	(void) fflush(stdout);

	/* iterate, reading from local user and then from chatserver */

	while((len = readln(buff, BUFFSIZE)) > 0) {
		buff[len - 1] = '\n';
		(void) send(conn, buff, len, 0);
		
		/* receive and print a line from the chatserver */
		if ((len = recvln(conn, buff, BUFFSIZE)) < 1)
			break;
		(void) printf(RECEIVED_PROMPT);
		(void) fflush(stdout);
		(void) write(STDOUT_FILENO, buff, len);

		(void) printf(INPUT_PROMPT);
		(void) fflush(stdout);
	}

	/* iteration ends when stdin or the connection indicates EOF */

	(void) printf("\nChat Connection Closed.\n");
	(void) send_eof(conn);
	exit(0);
}



I dont know if I should use the prof's defined "readln" and "await_contact"
or are there "predefined" methods in C like socket, or connect, listen,bind..

????
Last edited by LuciWiz : 20-Oct-2006 at 12:18. Reason: Please insert your C/C++ code between [cpp] & [/cpp] tags
  #2  
Old 20-Oct-2006, 12:28
nkhambal nkhambal is offline
Regular Member
 
Join Date: Jul 2004
Location: CA USA
Posts: 315
nkhambal is a jewel in the roughnkhambal is a jewel in the rough

Re: server/client.... multiple clients


The predefined functions given by your prof maps to functions in C socket library.

await_contact -> collection of socket()+bind()+listen()+accept() calls accpets returns a socket descriptor for the new client connection received. await_contact() is a blocking function because of accept() call. It blocks until a client connection arrives after which it returns with the descriptor for the new connection (different from the one on which it is listening). In you case it is stored in variable "conn" which is further used for sending (send ->send()) and receiving (recvln() -> recv()) .

Now to handle multiple client connections simultaneously, you have 3 possible ways to do it.

1. Start a new thread everytime await_contact returns and pass the new socket descriptor value ('conn') to that thread so that it can work with it independently without stopping the main thread which continues back up to await_contact() and listen for new connections from client.

2. Same as option 1 except fork() a new process instead of a thread. Just remember, creating a new process for each new client can be more resource expensive for the OS than creating a thread.

3. Use select() function call which provides a non-blocking way of handling multiple client connections without using thread per client or process per client approach. It stores all socket descriptors (server+ multiple 'conn's) in a descriptor set and samples (or polls) them regularly to see if any of them is ready for reading or writing i.e. recv() or accept() (for server descriptor) or send(). It then uses that socket descriptor and do the necessory I/O on the socket and when finished goes back to select() for polling the socket again.

If you google for select() or Beej's Guide to Network Programming, you will find good reference material.

Hope this helps.

Thanks.
  #3  
Old 21-Oct-2006, 01:50
Justin Fox Justin Fox is offline
Junior Member
 
Join Date: Sep 2006
Posts: 46
Justin Fox is on a distinguished road

Re: server/client.... multiple clients


ok, so i get the idea,

and i know to use.. pthread.h ...

but the parameters are very very confusing to me...

is there anyway someone could break down the params for me...

so each time the await_contact returns, i would call...

"ret = pthread_create();" somethin along those lines..

but how would i go about passing the connection from the

await_contact to the newly created thread?

just have a method that adds to the current thread,

like

void sendToThread(connection conn){

//create socket with param conn?
//then listen?

}

Justin...
  #4  
Old 21-Oct-2006, 02:56
Justin Fox Justin Fox is offline
Junior Member
 
Join Date: Sep 2006
Posts: 46
Justin Fox is on a distinguished road

Re: server/client.... multiple clients


ok, here is my revised server side application...

CPP / C++ / C Code:
/* chatserver.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>
#include <pthread.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);

/*--------------------------------------------------------------------

---
 *
 * Program: chatserver
 * Purpose: wait for a connection from a chatclient & allow users to 

chat
 * Usage:   chatserver <appnum>
 *
 

*---------------------------------------------------------------------

--
 */
void *sendStuff(connection conn)
{

int len = 0;
char buff[BUFFSIZE];

  	while((len = recvln(conn, buff, BUFFSIZE)) > 0) {
		(void) printf(RECEIVED_PROMPT);
		(void) fflush(stdout);
		(void) write(STDOUT_FILENO, buff, len);
		
		/* send a line to the chatclient */

		(void) printf(INPUT_PROMPT);
		(void) fflush(stdout);
		if ((len = readln(buff, BUFFSIZE)) < 1)
			break;
		buff[len - 1] = '\n';
		(void) send(conn, buff, len, 0);
	} 

	(void) send_eof(conn);
	(void) printf("\nChat Connection Closed.\n\n");
	//return 0;

}



int
main(int argc, char *argv[])
{
	connection	conn;
	int		len;
	char		buff[BUFFSIZE];
	pthread_t       newThread;

	if (argc != 2) {
		(void) fprintf(stderr, "usage: %s <appnum>\n", 

argv[0]);
		exit(1);
	}

	(void) printf("Chat Server Waiting For Connection.\n");

	/* wait for a connection from a chatclient */

        while(conn > 0)
        {
	conn = await_contact((appnum) atoi(argv[1]));
	if (conn < 0)
		exit(1);

        pthread_create(&newThread,NULL,sendStuff,*conn);
	
	(void) printf("Chat Connection Established.\n");
	
	/* iterate, reading from the client and the local user */



	/* iteration ends when EOF found on stdin or chat connection 

*/

	}// end of await_contact loop

}//end main





ok now, Im getting errors at argument 3 and 4 of pthread_create...

i dont think im fully understanding the parameters...

i thought 3 was the param of the method you wanted to execute in

the thread...

and 4 was the parameter for the method passed in param 3...

am I right?


thanks,


Justin
Last edited by LuciWiz : 21-Oct-2006 at 11:57. Reason: Please insert your C/C++ code between [cpp] & [/cpp] tags
  #5  
Old 21-Oct-2006, 04:11
nkhambal nkhambal is offline
Regular Member
 
Join Date: Jul 2004
Location: CA USA
Posts: 315
nkhambal is a jewel in the roughnkhambal is a jewel in the rough

Re: server/client.... multiple clients


pls post the errors.

The method you want to excuting in the thread is prototyped as

void * func_name (void *arg)

Have you done it.?
  #6  
Old 23-Oct-2006, 16:49
Justin Fox Justin Fox is offline
Junior Member
 
Join Date: Sep 2006
Posts: 46
Justin Fox is on a distinguished road

Re: server/client.... multiple clients


ok I got the thing to compile...

but after the client connects, im getting a

segmentation fault...i have no idea what that is..

here is the code for the server/client..

oh, I am also getting a warning: parameter 4 of 'pthread_create'
makes pointer from integer without cast? what does that mean?

CPP / C++ / C Code:

/* chatserver.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>
#include <pthread.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);
void *sendStuff(void *arg);

/*-----------------------------------------------------------------------
 *
 * Program: chatserver
 * Purpose: wait for a connection from a chatclient & allow users to chat
 * Usage:   chatserver <appnum>
 *
 *-----------------------------------------------------------------------
 */

int
main(int argc, char *argv[])
{
	connection     	conn;
	int		len;
	char		buff[BUFFSIZE];
	pthread_t       newThread;

	if (argc != 2) {
		(void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);
		exit(1);
	}

	(void) printf("Chat Server Waiting For Connection.\n");

	/* wait for a connection from a chatclient */

        while(conn > 0)
        {
	conn = await_contact((appnum) atoi(argv[1]));

        pthread_create(&newThread,NULL,sendStuff,conn);
	
	(void) printf("Chat Connection Established.\n");
	}// end of await contact loop
	
}

void *sendStuff(void *arg)
{

	int conn = *(int*)arg;

	int len = 0;
	char buff[BUFFSIZE];
printf("got to send stuff");
	    while((len = recvln(conn, buff, BUFFSIZE)) > 0) {
           (void) printf(RECEIVED_PROMPT); 
	   (void) fflush(stdout);
	   (void) write(STDOUT_FILENO, buff, len);

	/* send a line to the chatclient */

(void) printf(INPUT_PROMPT);					                
(void) fflush(stdout);
if ((len = readln(buff, BUFFSIZE)) < 1)
        break;
buff[len - 1] = '\n';
(void) send(conn, buff, len, 0);
}

        (void) send_eof(conn);			       
       	(void) printf("\nChat Connection Closed.\n\n");
				        
}//end sendStuff





CPP / C++ / C Code:
/* chatclient.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);

/*-----------------------------------------------------------------------
 *
 * Program: chatclient
 * Purpose: contact a chatserver and allow users to chat
 * Usage:   chatclient <compname> <appnum>
 *
 *-----------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	computer	comp;
	connection	conn;
	char		buff[BUFFSIZE];
	int		len;

	if (argc != 3) {
		(void) fprintf(stderr, "usage: %s <compname> <appnum>\n",
			       argv[0]);
		exit(1);
	}

	/* convert the compname to binary form comp */

	comp = cname_to_comp(argv[1]);
	if (comp == -1)
		exit(1);

	/* make a connection to the chatserver */

	conn = make_contact(comp, (appnum) atoi(argv[2]));
	if (conn < 0) 
		exit(1);

	(void) printf("Chat Connection Established.\n");
	(void) printf(INPUT_PROMPT);
	(void) fflush(stdout);

	/* iterate, reading from local user and then from chatserver */

	while((len = readln(buff, BUFFSIZE)) > 0) {
		buff[len - 1] = '\n';
		(void) send(conn, buff, len, 0);
		
		/* receive and print a line from the chatserver */
		if ((len = recvln(conn, buff, BUFFSIZE)) < 1)
			break;
		(void) printf(RECEIVED_PROMPT);
		(void) fflush(stdout);
		(void) write(STDOUT_FILENO, buff, len);

		(void) printf(INPUT_PROMPT);
		(void) fflush(stdout);
	}

	/* iteration ends when stdin or the connection indicates EOF */

	(void) printf("\nChat Connection Closed.\n");
	(void) send_eof(conn);
	exit(0);
}



so in all there are two problems..

the 4th param in 'pthread_create': making a pointer from integer without
cast.

and

segmentation fault in the chatserver application..

i think it has something to do with the:

Code:
while(conn > 0) { // the code in this loop. }
Last edited by LuciWiz : 24-Oct-2006 at 01:10. Reason: Please insert your C/C++ code between [cpp] & [/cpp] tags
  #7  
Old 23-Oct-2006, 17:15
nkhambal nkhambal is offline
Regular Member
 
Join Date: Jul 2004
Location: CA USA
Posts: 315
nkhambal is a jewel in the roughnkhambal is a jewel in the rough

Re: server/client.... multiple clients


Is "connection" typedefed has "Integer"? Atleast thats what it looks like from your "sendStuff" function.

You are not initializing "conn" anywhere before calling
CPP / C++ / C Code:
while(conn > 0)
{

}

How do you know for sure that "conn" is actually greater than 0. If you want to simply run continuously, just do
CPP / C++ / C Code:
while (1) 
{ 
/* Your accept code here */
}

Now to your thread part of the code.
This is what pthread_create looks like

CPP / C++ / C Code:
int  pthread_create(pthread_t  *  thread, pthread_attr_t * attr, void *
       (*start_routine)(void *), void * arg);

and this is what you have

CPP / C++ / C Code:
pthread_create(&newThread,NULL,sendStuff,conn);

The last argument should be a pointer. Now since your last variable "conn" is an integer, you need to cast it as void pointer when passing it to pthread_create as below.

CPP / C++ / C Code:
ad_create(&newThread,NULL,sendStuff,(void *)&conn);

The best way to troubleshoot is to use "printf" statements inside your code to see whats going on with the values you are passing down the functions.

For. e.g. Before calling pthread_create() you could printout the connection value as

CPP / C++ / C Code:
printf("Starting Client Thread. Socket ID: %d\n",conn);
/* Start thread */
ad_create(&newThread,NULL,sendStuff,(void *)&conn);

Also, you can capture and print the socket id inside the thread function "sendStuff".
CPP / C++ / C Code:
int conn = *((int*)arg);
printf("Starting to receive on Socket ID: %d\n",conn);

This will help you make sure, that what you are passing to pthread_create is what actually being used by "sendStuff" to send and receive. Try this and see what happens.


[/c]
  #8  
Old 23-Oct-2006, 17:48
Justin Fox Justin Fox is offline
Junior Member
 
Join Date: Sep 2006
Posts: 46
Justin Fox is on a distinguished road

Re: server/client.... multiple clients


k, will do...

yes, conn is an integer...

i looking into await contact, and at the end of the function,
it returns accept, which returns int.

thx for the (void*)&conn I would've never figured that out lol...

ill post when I modify...

thanks again,


Justin
  #9  
Old 23-Oct-2006, 20:54
Justin Fox Justin Fox is offline
Junior Member
 
Join Date: Sep 2006
Posts: 46
Justin Fox is on a distinguished road

Re: server/client.... multiple clients


ok, I changed it, and it compiled and works!

the server side that is...

now the client wont connect, i put a

printf("EXIT STATUS");
in the

CPP / C++ / C Code:

if(conn < 0)
{
   printf("EXIT STATUS");
   exit(1);
}
// put that in the chatclient.c



umm, I dont see why it wouldn't connect, the await_contact on the
server side is still in the main function...

oh, I also added a

CPP / C++ / C Code:
printf("in await loop");

in the chatserver.c

so see if it even go into the while(1){} loop

Justin


CPP / C++ / C Code:


/* chatserver.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>
#include <pthread.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);
void *sendStuff(void *arg);

/*-----------------------------------------------------------------------
 *
 * Program: chatserver
 * Purpose: wait for a connection from a chatclient & allow users to chat
 * Usage:   chatserver <appnum>
 *
 *-----------------------------------------------------------------------
 */

int
main(int argc, char *argv[])
{
	connection     	conn;
	int		len;
	char		buff[BUFFSIZE];
	pthread_t       newThread;

	if (argc != 2) {
		(void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);
		exit(1);
	}

	(void) printf("Chat Server Waiting For Connection.\n");

	/* wait for a connection from a chatclient */

        while(1)
        {
	(void) printf("in await loop.\n");
	
	conn = await_contact((appnum) atoi(argv[1]));

        pthread_create(&newThread,NULL,sendStuff,(void *)&conn);
	
	(void) printf("Chat Connection Established.\n");
	}// end of await contact loop
	
}

void *sendStuff(void *arg)
{

	int conn = *(int*)arg;

	int len = 0;
	char buff[BUFFSIZE];
printf("got to send stuff");
	    while((len = recvln(conn, buff, BUFFSIZE)) > 0) {
           (void) printf(RECEIVED_PROMPT); 
	   (void) fflush(stdout);
	   (void) write(STDOUT_FILENO, buff, len);

	/* send a line to the chatclient */

(void) printf(INPUT_PROMPT);					                
(void) fflush(stdout);
if ((len = readln(buff, BUFFSIZE)) < 1)
        break;
buff[len - 1] = '\n';
(void) send(conn, buff, len, 0);
}

        (void) send_eof(conn);			       
       	(void) printf("\nChat Connection Closed.\n\n");
				        
}//end sendStuff






CPP / C++ / C Code:

/* chatclient.c */

#include <stdlib.h>
#include <stdio.h>
#include <cnaiapi.h>

#define BUFFSIZE		256
#define INPUT_PROMPT		"Input   > "
#define RECEIVED_PROMPT		"Received> "

int recvln(connection, char *, int);
int readln(char *, int);

/*-----------------------------------------------------------------------
 *
 * Program: chatclient
 * Purpose: contact a chatserver and allow users to chat
 * Usage:   chatclient <compname> <appnum>
 *
 *-----------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	computer	comp;
	connection	conn;
	char		buff[BUFFSIZE];
	int		len;

	if (argc != 3) {
		(void) fprintf(stderr, "usage: %s <compname> <appnum>\n",
			       argv[0]);
		exit(1);
	}

	/* convert the compname to binary form comp */

	comp = cname_to_comp(argv[1]);
	if (comp == -1)
		exit(1);

	/* make a connection to the chatserver */

	conn = make_contact(comp, (appnum) atoi(argv[2]));

	if (conn < 0){
	 printf("EXIT STATUS"); 
		exit(1);
		}

	(void) printf("Chat Connection Established.\n");
	(void) printf(INPUT_PROMPT);
	(void) fflush(stdout);

	/* iterate, reading from local user and then from chatserver */

	while((len = readln(buff, BUFFSIZE)) > 0) {
		buff[len - 1] = '\n';
		(void) send(conn, buff, len, 0);
		
		/* receive and print a line from the chatserver */
		if ((len = recvln(conn, buff, BUFFSIZE)) < 1)
			break;
		(void) printf(RECEIVED_PROMPT);
		(void) fflush(stdout);
		(void) write(STDOUT_FILENO, buff, len);

		(void) printf(INPUT_PROMPT);
		(void) fflush(stdout);
	}

	/* iteration ends when stdin or the connection indicates EOF */

	(void) printf("\nChat Connection Closed.\n");
	(void) send_eof(conn);
	exit(0);
}

Last edited by LuciWiz : 24-Oct-2006 at 01:12. Reason: Please insert your C/C++ code between [cpp] & [/cpp] tags
  #10  
Old 23-Oct-2006, 23:17
nkhambal nkhambal is offline
Regular Member
 
Join Date: Jul 2004
Location: CA USA
Posts: 315
nkhambal is a jewel in the roughnkhambal is a jewel in the rough

Re: server/client.... multiple clients


What port is server listening on.? By appnum i think you mean the "port number"

Is this a Windows machien or a unix machine that you are working on?

Each type of OS gives different APIs to print the reason for disconnection. For.e.g Unix has perror() while Windows has WSAGetLastError (I think!! I work on Unix mostly).

I suggest you read this before going forward. It gives good info on Network Programming.

Beej's Guide to Network Programming Using Internet Sockets

Thanks,
 
 

Recent GIDBlogProblems with the Navy (Enlisted) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple Domain Hosting – the best way to save money!!! luvila Web Hosting Advertisements & Offers 0 07-Aug-2006 04:03
Multiple Clients Trouble Golmal C Programming Language 1 16-May-2006 02:43
Multiple Domain Hosting – save your money!!! luvila Web Hosting Advertisements & Offers 0 30-Jan-2006 07:32
Linker errors with multiple file progam nkhambal C Programming Language 2 24-Apr-2005 02:37
strange sizeof(structure) - multiple of 8 pinkpanther C Programming Language 11 30-May-2004 07:20

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 17:39.


vBulletin, Copyright © 2000 - 2010, Jelsoft Enterprises Ltd.