C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old May 24th, 2003, 11:44 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 26
keeping multiple tcp connections open after one closes

i have this chat program. clients connect to the server, and the server broadcasts messages that it recieves. the server is multithreaded, and the clients are single threaded. my problem is that when one client logs off the server starts getting errors. i think it closes the socket when one client signs off, anyway, here is the server side code, (thanks for any help i know its a big chunk of stuff to look at):
Code:
/*****************************************
**		chat_server_main.cpp			**
**										**
**		server for the chat program		**
**		originally started on 5/25/03   **
*****************************************/

#include <stdio.h>
#include <winsock.h>
#include <process.h> 
#include "my_time.h"

#define		NO_FLAGS_SET    0
#define		PORT            6969
#define		MAX_CLIENTS		25
#define		BUFFER			250
#define		NAME_LEN		15
#define		LIST_SIZE		400

/* STRUCTURES */
struct message
{
	char	data[BUFFER];
	char	name[NAME_LEN];
	bool	list_data_flag;
	char	room_array[LIST_SIZE];
};	

struct client_data
{
	SOCKET			client_sock;
	SOCKADDR_IN		client_addr;
};


/* GLOBAL VARIABLES */		
int					num_clients = 0;			//keep track of how many clients connected
CRITICAL_SECTION	critSec;					//used for printf and global variable incrementing
char				room_list[LIST_SIZE];		//list of people in the room
SOCKET				client_list[MAX_CLIENTS];	//handles to the sockets
int					thread_id = 0;


/*  THREAD FUNCTION PROTOTYPES */
void talkToClient(void *cs);
void send_list(void *ptr);


/*  MAIN  */
int main()
{
	WSADATA		wsaData;				
	SOCKET		hListenServSocket;	
	SOCKADDR_IN	serverSockAddr;	
	
	int			addrLen = sizeof(SOCKADDR_IN),	status = 0;	
	DWORD			threadID,	list_threadID;						
	time_freeze	da_time;
	
	InitializeCriticalSection(&critSec);	
	
	// 1. Initialize WSA, the Window Socket API
	if( ( status = WSAStartup ( MAKEWORD(1, 1), &wsaData )) != 0) {return 1;}
	
	// 2. Create a socket
	if ((hListenServSocket = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
	{
		if ((status = WSACleanup()) == SOCKET_ERROR) printf("Error in creating socket\n");
		return 1 ;
	}
	
	// 3. Initialize server socket info 
	memset(&serverSockAddr, 0, sizeof(serverSockAddr));		//set up server info
	serverSockAddr.sin_family       = AF_INET;				
	serverSockAddr.sin_addr.s_addr  = htonl(INADDR_ANY);	   
	serverSockAddr.sin_port         = htons(PORT);		// host to network 
	
	// 4. Bind the socket with the address
	status = bind (hListenServSocket, (LPSOCKADDR) &serverSockAddr,sizeof(serverSockAddr));
	if (status == SOCKET_ERROR) { printf("Binding error\n"); return 1;}
	
	// 5. Listen for connections
	if ((status = listen ( hListenServSocket, MAX_CLIENTS )) == SOCKET_ERROR) 
	{ printf("Listen error\n"); return 1;}
	
	/* display startup info to the user */
	gimme_time(da_time, true);
	printf("[][][][]***(( Chat server now listening on port %u ))***[][][][]\n",PORT);
	printf("[][][][]***(( Serving a maximum of %u   clients      ))***[][][][]\n",MAX_CLIENTS);
	
	SOCKET		hNewServSocket;			//client socket
	SOCKADDR_IN	clientSockAddr;			// the clients address structure
	client_data	client_handle[MAX_CLIENTS];
	bool			start_list_thread = true;
	
	while(1)
	{
		// 6. Accept connection request when one received
		hNewServSocket = accept (hListenServSocket, (LPSOCKADDR) &clientSockAddr, &addrLen);
		if (hNewServSocket == INVALID_SOCKET) { printf("Accept error\n"); return 1; }
		printf("\nClient accepted, now serving %u clients", num_clients + 1);
		
		// add client to list; setup struct to pass to thread
		client_list[num_clients] = hNewServSocket;
		client_handle[num_clients].client_addr = clientSockAddr;
		client_handle[num_clients].client_sock = hNewServSocket;
		
		if ((threadID = _beginthread (talkToClient, 0, (void *) &client_handle[num_clients])) == -1)
		{ 
			printf("Thread creation error\n");
			status = closesocket(hNewServSocket);
			if (status == SOCKET_ERROR) printf("Socket closing error\n");
		}
		
		if(start_list_thread)
		{
			if ((list_threadID = _beginthread (send_list, 0, NULL)) == -1)
			{ 
				printf("List thread creation error\n");
				status = closesocket(hNewServSocket);
				if (status == SOCKET_ERROR) printf("Socket closing error #%u\n", WSAGetLastError());
			}
			start_list_thread = false;
		}	  
	} /* while */	
	
	return 1;
}

// talkToClient()  - handles each client - recieves their message & broadcasts it to all clients
void talkToClient(void *cs)
{
	bool	exit = false, first_connect = true;
	int		nBytesSent = 0, nBytesRecvd = 0, myID = 0;										
	message   incoming_data, outgoing_data;
	client_data *ptr = (struct client_data *)cs;		
	SOCKET  hNewServSocket = (SOCKET)ptr->client_sock;	
	
	// increment # of threads and clients
	thread_id++;
	num_clients++;
	myID = thread_id;
	
	printf("\nThread %u has started\n", myID);
	
	//initialize data structures
	incoming_data.list_data_flag = false; outgoing_data.list_data_flag = false;
	strcpy(incoming_data.data,""); strcpy(incoming_data.name,""); strcpy(incoming_data.room_array,"");
	strcpy(outgoing_data.data,""); strcpy(outgoing_data.name,""); strcpy(outgoing_data.room_array,"");
	
	// enter teh send recieve/loop	
	while(!exit)	
	{
		// (a) Receive 
		if (((nBytesRecvd = recv(hNewServSocket,(char *) &incoming_data, 
			sizeof incoming_data,NO_FLAGS_SET)) == 0) || (nBytesRecvd == SOCKET_ERROR))
		{
			if(nBytesRecvd == 0){ printf("Gracefully shutting down...\n");}
			else
			{
				EnterCriticalSection(&critSec);
				printf("recv: Thread %u Failed with error #%u\n", myID, WSAGetLastError());
				LeaveCriticalSection(&critSec);
			}
			exit = true;
			break;
		}
		
		// if this is first time connecting, then log the client's info
		if(first_connect)
		{
			
			printf("Client name is %s , client address is %x\n",incoming_data.name , 
				ptr->client_addr.sin_addr);
			
			//add teh client to the room list now that we have their nick name
			strcat(room_list, incoming_data.name); strcat(room_list, "-");
			first_connect = false;
		}
		
		// (b) Process
		strncpy(outgoing_data.name,incoming_data.name,NAME_LEN);
		strncpy(outgoing_data.data,incoming_data.data,BUFFER); 
		outgoing_data.list_data_flag = false;
		strcpy(outgoing_data.room_array, ""); 
		
		// (c) Broadcast message to all of the clients logged in
		for(int y = 0; y < num_clients;y++)
		{
			nBytesSent = send(client_list[y],(char *) &outgoing_data, 
				sizeof(outgoing_data),NO_FLAGS_SET);
			
			if ((nBytesSent == 0) || (nBytesSent == SOCKET_ERROR))
			{
				if(nBytesSent == 0){ printf("Gracefully shutting down...\n");}
				else
				{
					EnterCriticalSection(&critSec);
					printf("send: Thread %u Failed with error #%u\n", myID, WSAGetLastError());
					LeaveCriticalSection(&critSec);	
				}	
				exit = true;
				break;
			}
		}
		
		printf("\nThread %u is broadcasting\n", myID);
	} // while end	 
	
	//remove the client from the client_array
	for(int m = 0; m < num_clients; m++)
	{
		if(client_list[m] == hNewServSocket)
		{
			client_list[m] = client_list[num_clients - 1];
			client_list[num_clients - 1] = NULL;
		}
	}
	
	//decrement the # of clients connected
	num_clients--;
	
	// terminate the connection with the client
	printf("%s has disconnected...Connection being closed\n",incoming_data.name);
	shutdown    ( hNewServSocket, 1);
	closesocket ( hNewServSocket );
	
	printf("Thread %u has ended\n", myID);
}		

/*  send_list this thread sends out the list once every 5 seconds only if the list has changed	**
**  size since the last time.																	*/

void send_list(void *ptr)
{
	char old_room_list[LIST_SIZE]; 
	int bytes_sent = 0;
	message list_out;
	
	strcpy(old_room_list, room_list);						// get a copy of the list
	printf("List thread starting\n");
	
	while(num_clients > 0)		//while we have clients
	{
		Sleep(5000);			// once every 5 seconds
		if((strcmp(old_room_list, room_list)) != 0)			// list is either bigger/smaller
		{
			strcpy(old_room_list, room_list);				// update our copy of the list
			list_out.list_data_flag = true;					// set flag for client 
			strcpy(list_out.room_array,room_list);			// setup the data packet 
			for(int y = 0; y < num_clients; y++)			// send to all clients
			{
				bytes_sent = send(client_list[y], (char *) &list_out,
					sizeof (list_out), NO_FLAGS_SET);
				if ((bytes_sent == 0) || (bytes_sent == SOCKET_ERROR))
				{
					// bytes_sent = 0 indicates  graceful shutdown.
					EnterCriticalSection(&critSec);//mistah Marshall Brain we do
					printf("Failed with error #%u\n", WSAGetLastError());
					LeaveCriticalSection(&critSec);		
				} // end if
			}	//end for
		}	//end if
	}	// end while
	
	printf("List thread ending\n");
}

Last edited by infamous41md : May 27th, 2003 at 09:12 PM.

Reply With Quote
  #2  
Old May 25th, 2003, 11:06 AM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,868 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 2 Days 3 h 12 m 53 sec
Reputation Power: 480
It looks to me that the server should have exited with an error right after the first client connects. After the first accept and thread creation, you are not going back to listen, but rather you immediately go back to accept. accept returns INVALID_SOCKET on error, which you test for and exit out of the server. Yet you say that's not how it's going down.

If accept is not returning INVALID_SOCKET, then it would appear that your while(1) loop would just keep churning away creating more and more threads all trying to use that same socket created by the accept(). Then when you close the socket in one of the threads, the others do not have a valid socket. I don't know what error messages you're getting, but I assume it's something about an invalid socket.

Also, you are not listening for further connects, so no other client will be able to connect.

Suggestion:
Move the listen call into the while(1) loop as the first thing it does. Then when you accept, you create a thread for that client and return to listen. Since each thread declares its own socket to which you copy the socket that accept returns, the client socket variable in main() should be reusable.

Enhancement suggestion:
Instead of just passing the socket to the thread, create a struct that contains the socket and the client's SOCKADDR_IN. Then one of the things the thread could do would be to display a report identifying the client who just connected and then also report when that client disconnects. This could be modified to a log-file or accounting file entry.

Reply With Quote
  #3  
Old May 25th, 2003, 07:57 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 26
i made some changes to teh above code. still though i am getting the same problem. so i decided instead of reusing the same client socket variable, to make an array of them and use a new one each time. still the same thing is happening, only slightly different now. i've been trying to debug it, and from what i can tell, what happens is that recv() returns a 0 and then it closes down. the only problem is that im not sure which thread i am looking at when this happens? how is one supposed to debug multi threaded apps?

edit: now this is just odd. if i start it up with 5 or 6 clients logged on, then the following happens:
-if one of the last clients to log on decides to disconnect, then everything works fine.
-if the first or second client to log on decides to disconnect, then everything gets fuxx0red.

also, what would be a good way to exit the program? after all the threads finish the program just sits there. it's somewhere in the while loop waiting for a new client.

Last edited by infamous41md : May 25th, 2003 at 08:21 PM.

Reply With Quote
  #4  
Old May 26th, 2003, 12:20 AM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,868 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 2 Days 3 h 12 m 53 sec
Reputation Power: 480
Well, I keep hearing that debugging multi-threaded programs can be difficult. I don't have any direct experience with it, but I have debugged embedded programs.

I would suggest using debug statements, AKA "trace statements". Print to the screen statements of where in the program it's being called from and what certain key variable values are. Then you can see from the debug statements exactly what happened when. You can start off with a few debug statements scattered where you think the problem might be. Then add statements around where things appear to be going wrong.

I suggested that you pass a struct to the thread instead of just the socket. You should add an auto-increment serial number to main() and have it assign that number to the new thread and increment it. Also have main() output a value for the client socket -- it's simply an integer in Linux and I think it's also an integer in Winsock; you might have to play around with this one.

Every thread should emit a debug statement when it starts, encounters an error condition, and exits. In each one, it should output its serial number. The start statement should also report the client address and the SOCKET value (after having been assigned to the local SOCKET variable). The exit statement should also report the local SOCKET value. Hopefully that would help to settle some questions about socket assignment.


As for a good way to exit the program, you could try running yet another thread that looks for keyboard input. When the user enters a command to terminate the server, then it can shut everything down in an orderly fashhion -- for that, you may need to keep track of all the threadID's.

Suggestion:
Do the keyboard input in the main function. Put the listen/accept logic in a thread that is the only thread that main() starts. Then that thread will create all the client-handling threads.

Reply With Quote
  #5  
Old May 26th, 2003, 03:09 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 26
ok thanks, that sounds like good advice to me. but what are, "embedded programs?"

Reply With Quote
  #6  
Old May 26th, 2003, 04:49 PM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,868 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 2 Days 3 h 12 m 53 sec
Reputation Power: 480
Quote:
Originally posted by infamous41md
ok thanks, that sounds like good advice to me. but what are, "embedded programs?"


The first applications for microprocessors involved embedding them into other devices as a replacement for discrete logic networks. We continue that practice, such that these microprocessors are found in almost every appliance we have, including TVs, microwave ovens, stove, washing machines, and (several) in your car. The programs for these embedded microprocessors are called "embedded programs".

If you have ever or will ever study logic hardware design, you will see that it can take a rather complex network of many (read tens and hundreds) AND, OR, and NOT gates (and several hybrids thereof) to create a circuit that will output complex digital signals in response to a large set of input conditions. And the task of maintaining an existing logic circuit or modifying it to include additional inputs or different outputs can be daunting.

A microprocessor and a small amount of "glue logic" circuitry replaced all that hard-wired circuitry, leading to size and cost reduction by the elimination of parts and reducing the cost of design and maintenance. And it opened the door to creating even more complex control logic.

Now more recently, we've returned to complex logic circuits, only they are developed through software running on workstations and loaded into a single IC device called a "field-programmable gate array" (FPGA).

The embedded software I develop handles the overall sequence of control, performs I/O into and out of the device, and interfaces with the FPGA. Since I test my code on production hardware, the only way I can debug the code is to observe how the device operates, have it output debug messages, and read through the code. The most productive way to get debug information out of the device is through the debug messages, so I've had an awful lot of experience with that method.

Reply With Quote
  #7  
Old May 26th, 2003, 05:48 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 26
wow that's pretty cool. i've always wanted to know how to hack my car LCD display and have it say funny stuff, you can do that? . i did a chapter or 2 on logic gates, it was pretty interesting stuff b/c u could actually see what's really going on in there.

Reply With Quote
  #8  
Old May 27th, 2003, 12:16 AM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed Expert (3500 - 3999 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 3,868 dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)dwise1_aol User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 1 Month 2 Days 3 h 12 m 53 sec
Reputation Power: 480
I feel fortunate that I got into computers via the hardware -- Air Force training as a computer repairman. Then I read the classic SAMS "bug books" on the 8080A, which was THE Intel microprocessor at the time (circa 1978). Then with that background to start with, I earned my computer science degree. I think that knowing about the hardware and how it works gave me a different perspective than the other students, for whom it must have all been very abstract.

So my hardware knowledge makes me a good candidate for embedded programming; the vast majority of my professional work has been embedded. In one job, the EE had very little experience with digital ICs, so I ended up doing most of the interface designs.

As for hacking your LCD display, that would take a bit of work. Though the fonts are stored in ROM as is the application code of the device talking to it. You can disassemble the code, but it's still a lot of work. I'll leave that project for you [grin].

Let me know how you solve the TCP problem.

Reply With Quote
  #9  
Old May 27th, 2003, 04:10 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 26
the way this program behaves confuses me. if the first client to logon disconnects, then all future requests fail with WSAENOTSOCK. but if instead say the third or fourth client to log on disconnects, nothing out of the ordinary happens. very confusing. i'll have to keep trying i guess, i 'll let u know how it turns out.

EDIT: of course, the problem was some faulty logic on my part. the problem was that after a client left i never removed them from the array that was used to broadcast messages to all the clients. then when the next client sent a message to the server, it would try to broadcast that message to all the clients, including the one who was not signed on, so it then gave me the "NOT A SOCKET ERROR."
question: are u aware of any libraries that take a WSA Error message and output a nice text description of the error? if not i think im going to have to make one

Last edited by infamous41md : May 27th, 2003 at 08:45 PM.

Reply With Quote
  #10  
Old May 27th, 2003, 09:02 PM
Scorpions4ever's Avatar
Scorpions4ever Scorpions4ever is offline
Banned ;)
Dev Shed God 6th Plane (7500 - 7999 posts)
 
Join Date: Nov 2001
Location: Glendale, Los Angeles County, California, USA
Posts: 7,589 Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level)Scorpions4ever User rank is General (90000 - 100000 Reputation Level) 
Time spent in forums: 1 Month 1 Day 22 h 42 m 40 sec
Reputation Power: 1001
You can use WSAGetLastError() and pass the error code to FormatMessage(). However, there are some problems with this approach, on some versions of Windoze (actually, the version of Winsock, to be precise). For a better solution, you might want to write your own error translator. Better still, use someone else's work, like this:
http://www.beginthread.com/Article/...r%20Translator/

Hope this helps

Last edited by Scorpions4ever : May 27th, 2003 at 09:04 PM.

Reply With Quote
  #11  
Old May 27th, 2003, 09:20 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level)infamous41md User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 26
scorpions<< cool thanks, exactly what i was looking for. i figured that there had to be someone else who found those cryptic error #'s annoying and did something about it.

edit: the code in my first post now has the completed and correct code if anyone was curious.

Last edited by infamous41md : May 27th, 2003 at 09:28 PM.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages