• Advertisement
Sign in to follow this  

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

This topic is 4128 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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 != INVALID_SOCKET){
			send(clientSockets,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 = 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 << "\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,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
Advertisement
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
Sign in to follow this  

  • Advertisement