Sign in to follow this  
dadads

Can anyone help me with my small chat program? I'm getting weird output

Recommended Posts

I'm making a simple chat program using simple winsock stuff, and the string class. Basically, after you start the program you can choose to start a chat server or to be a client. If you become a client, you will have The program connects through port 2006 (defined as a macro on the top of the source code). You can host a server and open a client in the same computer and make them connect using the 127.0.0.1 IP address. Here's the code
#define SERVER_PORT 2006

#include <iostream>
#include <winsock.h>
#include <process.h>

using namespace std;

int server();
int client();
void error(LPCSTR);
void clientHandler(void*);
void serverHandler(void*);
void broadcast(string);
void appendMessage(string);

WORD sockVersion;
WSADATA wsaData;
SOCKET main_socket;
string* prog_messages = new string[5];
int total_messages = 0;

//=========================================================================================================
// MAIN FUNCTION
//=========================================================================================================

int main(){
	//Initialize variables
	int ans;
	
	//Friendly message
	cout << "===============================\n     Console Chat Program\n===============================\n\n";
	
	//Initialize Winsock
	cout << "Initializing socket...";
	sockVersion = MAKEWORD(1, 1);
	WSAStartup(sockVersion, &wsaData);
	cout << " Done!\n";
	
	//Choose mode
 	cout << "\nSELECT MODE\n\n 1. Server\n 2. Client\n";
 	while (true){
 		cout << "\nMode: ";
 		cin >> ans;
 		if (ans == 1 || ans == 2){
 			break;
 		}else{
 			error("Invalid mode");
 		}
 	}
 	if (ans == 1){
 		server();
 	}else{
 		client();
 	}
	
	//Program ended
	cout << "\nProgram ended\n";
	
 	system("pause");
	return 0;
}

void error(LPCSTR message){
	cout << "[" << message << "]\n";
}

SOCKET* clientSockets;
SOCKADDR_IN* clientInfo;
int connectedClients;
int maxClients;
int temp;

//=========================================================================================================
// START SERVER
//=========================================================================================================

int server(){

	// Server start message
	system("cls");
	cout << "Server started\n\n";
	
	// Get max client input
	cout << "Max clients: ";
	cin >> maxClients;
	cout << "\n";
	
//=========================================================================================================
// INITIALIZE SERVER
//=========================================================================================================

	// Try to initialize socket
	temp = 0;
	while (true){
		cout << "Initializing socket...";
 		main_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	 	if (main_socket == INVALID_SOCKET){
	 		if (temp == 10){
	 			cout << " Failed, bailing out\n";
	 			return -1;
	 		}else{
			 	temp ++;
			 	cout << " Failed, retrying (" << temp << ")\n";
			}
		}else{
			cout << " Done!\n";
			break;
		}
	}
	
	// Set server address information
	cout << "Filling address info...";
	SOCKADDR_IN serverInfo;
	serverInfo.sin_family = AF_INET;
	serverInfo.sin_addr.s_addr = INADDR_ANY;
	serverInfo.sin_port = htons(SERVER_PORT);
	cout << " Done!\n";
	
	// Bind the socket
	cout << "Binding socket...";
	if (bind(main_socket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr)) == SOCKET_ERROR) {
		return -1;
	}else{
		cout << " Done!\n";
	}
	
	// Set the socket to listen-mode
	cout << "Start listening...";
	if (listen(main_socket, maxClients) == SOCKET_ERROR){
		return -1;
	}else{
		cout << " Done!\n";
	}
	
	// Create the client socket and info array
	cout << "Reserving array memory...";
	try{
 		clientSockets = new SOCKET[maxClients];
	 	clientInfo = new SOCKADDR_IN[maxClients];
	 	cout << " Done!\n";
	}catch(int x){
	 	cout << " Failed!\n";
	}
	
	// Start client handler threads
	cout << "Starting client-handler threads...";
	for (int i=0;i<maxClients;i++){
		temp = i;
		_beginthread(clientHandler,0,0);
	}
	cout << " Done!\n";

//=========================================================================================================
// START SERVER INPUT
//=========================================================================================================

	// Server is ready
	cout << "Server ready!\n\n";
	system("pause");
	system("cls");
	
	// Start receiving input
	cout << "\nInput: ";
	while (true){
		string input;
		cin >> input;
		if (input.length() > 256){
			input = input.substr(0,256);
		}
		appendMessage("> " + input);
		broadcast(input);
	}

	// End of server module
	return 0;
}

int client(){
	system("cls");
	cout << "Client started\n\n";
	while (true){
		LPHOSTENT hostEntry;
		in_addr hostAddress;
		//Get server's IP
		while (true){
			char addr[16];
			cout << "Server IP: ";
			cin >> addr;
			hostAddress.s_addr = inet_addr(addr);
			//Create host information
			hostEntry = gethostbyaddr((const char *)&hostAddress, sizeof(struct in_addr), AF_INET);
			if (!hostEntry){
				error("Invalid host info");
			}else{
				break;
			}
		}
		//Initialize socket
		main_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		
		if (main_socket == INVALID_SOCKET){
			error("Unable to initialize socket");
		}else{
			// Fill a SOCKADDR_IN struct with address information
			SOCKADDR_IN serverInfo;
			serverInfo.sin_family = AF_INET;
			serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
			serverInfo.sin_port = htons(SERVER_PORT);
			
			// Connect to the server
			if (connect(main_socket,(LPSOCKADDR)&serverInfo,sizeof(struct sockaddr)) == SOCKET_ERROR){
				error("Unable to connect to server");
			}else{
				break;
			}
		}
	}
	
	_beginthread(serverHandler,0,0);
	
	//Connection process completed!
	cout << "Connection established!\n\n";
	cout << "Input: ";
	
	while (true){
		string input;
		cin >> input;
		if (input.length() > 256){
			input = input.substr(0,256);
		}
		appendMessage("> " + input);
		send(main_socket,input.c_str(),strlen(input.c_str()),0);
	}
	
	//Finish
	closesocket(main_socket);
	WSACleanup();
}

void clientHandler(void* ch){
	int index = temp;
	while (true){
 		//Accept client
 		int size = sizeof(clientInfo[index]);
	 	clientSockets[index] = accept(main_socket,(LPSOCKADDR)&clientInfo[index],&size);
	 	if (clientSockets[index] != INVALID_SOCKET) {
	 		string temp = inet_ntoa(clientInfo[index].sin_addr);
			appendMessage("Client accepted (" + temp + ")");
			while (true){
				//Print client's messages
				char buffer[256] = "";
				if (recv(clientSockets[index],buffer,256,0) == SOCKET_ERROR){
	 			string temp = inet_ntoa(clientInfo[index].sin_addr);
	 			appendMessage("Client disconnected (" + temp + ")");
					break;
				}else{
					string temp = (1,buffer);
					appendMessage("> " + temp);
				}
			}
			closesocket(clientSockets[index]);
		}
	}
}

void broadcast(string message){
	for (int i=0;i<maxClients;i++){
		if (clientSockets[i] != INVALID_SOCKET){
			send(clientSockets[i],message.c_str(),strlen(message.c_str()),0);
		}
	}
}

void serverHandler(void* ch){
	while (true){
 		char buffer[256] = "";
		if (recv(main_socket,buffer,256,0) != SOCKET_ERROR){
			string temp1 = "> ";
			string temp2 = (1,buffer);
			appendMessage(temp1 + temp2);
		}
	}
}

void appendMessage(string message){
	if (total_messages == 5){
  		for (int i=0;i<4;i++){
  			prog_messages[i] = prog_messages[i + 1];
		}
		prog_messages[4] = message;
	}else{
		prog_messages[total_messages] = message;
		total_messages ++;
	}
	
	//Re-display
	system("cls");
	for (int i=0;i<total_messages;i++){
 		cout << prog_messages[i] << "\n";
	}
	cout << "\nInput: ";
}
The weird thing is that if I input "hello world", what comes out in the screen (of the other member of the chat room) is: > hello > world When what I want as an output is: > hello world My guesses: 1. There's something wrong with inputs, the space character acting as a delimiter I used this method: "string input; cin >> input;" for user chat input 2. Might be something to do with the fact that I made the string array using dynamic memory (string* prog_messages = new string[5]). The program reads the string array through the "appendMessage" function and then outputs the chat-text. 3. Unlikely, but it might be something to do with sending data through winsock. Something like this: "send(clientSockets[i],message.c_str(),strlen(message.c_str()),0);", where "message" is the string variable. FYI: The commenting for the client section is not yet completed, I'm currently thinking hard about this problem. [Edited by - dadads on October 3, 2006 10:00:23 AM]

Share this post


Link to post
Share on other sites
1) That's a lot of code for 'code' tags. Please use a 'source' box instead.

2) Guess (1) is correct (at least, is the only one that would explain the symptom). To read text a line at a time, use std::getline(source stream, target string).

Share this post


Link to post
Share on other sites
errr...
For the std::getline() function, what argument/variable should I use for the "source stream" ?

*edit
oh, nevermind. It turns out to be std::cin

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this