Thread: SO close to finishing chat program...!

  1. #1
    Registered User
    Join Date
    Oct 2002
    Posts
    155

    SO close to finishing chat program...!

    I am extremely close to finishing my chat program using sockets but it appears that I have a problem. The message received from the other user is partially garbled after 4 characters. I do not know why. If anyone could find out why it is doing so I

    WOULD APPRECIATE IT GREATLY!!!

    I have been looking for this error for hours now and I just don't see why it's doing so... anyway, here is my messy code:

    Code:
    //***INCLUDES***
    
    
    #include <fstream.h>  //for cout and cin, and to potentially keep a log of your chat
    #include <winsock.h>  //for sockets and WSADATA data structures
    #include <string.h>   //string functions
    #include <ctype.h>    //toupper function
    #include <cstdlib.h>  //for the exit() function
    #include <conio.h>    //allows use of color and clrscr();
    #include <iomanip.h>  //lets one use the setbase() command
    using namespace std;
    
    
    //***GLOBAL CONSTANTS***
    
    
    const short int WINSOCK_VERSION = 0x0202;
    const int PORT = 3163;        //the port used for data sending  
    const int MAX_LEN = 4096;
    
    
    //***FUNCTION PROTOTYPES***
    
    
    void start_winsock(WSADATA& data);
    //precondition: WSADATA structure has been declared
    //postcondition: Either Winsock started up or the program ended if there was an initialization error
    
    void output_winsock_data(WSADATA data);
    //precondition: WSADATA structure has been declared
    //postcondition: Information pertaining to Winsock has been outputted
    
    void open_socket(SOCKET& MySocket);
    //precondition: MySocket has been declared
    //postcondition: If socket() could not be opened, the program terminates
    
    void chat_server(SOCKET& MySocket, bool& contin);
    
    void chat_client(SOCKET& MySocket, bool& contin);
    
    void bind_socket(SOCKET& MySocket, SOCKADDR_IN& bindToAddress);
    
    void listen_on_stream_socket(SOCKET& MySocket);
    
    void accept_msg_socket(SOCKET& MySocket, SOCKET& theClient, SOCKADDR_IN& fromAddress, int& length);
    
    void receive_message(SOCKET& theClient, char incoming[MAX_LEN]);
    
    void find_host(char Server[MAX_LEN], hostent* host, int& address, SOCKADDR_IN& remoteAddress);
    
    void connect_host(SOCKET& MySocket, SOCKADDR_IN& remoteAddress);
    
    void send_reply(SOCKET& Socket, char outgoing[MAX_LEN]);
    
    void changecolor(char* word, int color);
    //precondition: word has been given a string value, and color has been given a number
    //postcondition: conio function textcolor() has been called within function changecolor,
    //changing the char* word into the color given by the int color.
    
    void slowtype(char* word);
    //precondition: word has a value
    //postcondition: word has been outputted slowly (one letter per 70 milliseconds)
    
    void flushin();
    
    
    //***FUNCTION BODIES***
    
    
    int main(){
    	SOCKET MySocket;    // create the socket itself
        WSADATA data;  //contains data pertaining to WinSock
    	char abc;
    	bool contin = true;
    	
    	changecolor("Nakeerb's Chat Program\r\n\r\n", LIGHTRED);	
        changecolor("Utilizing #include <winsock>...\r\n", LIGHTGREEN);
        cout << setbase(16) << "Version: " << WINSOCK_VERSION << endl;
    	slowtype("Initializing WSAStartup:\n");
    	
        start_winsock(data);
        output_winsock_data(data);
    	open_socket(MySocket);
        
    	cout << "Press a key to continue.\n";
        getch();
    
    	do{
    		clrscr();
    		cout << "\n\n\n";
    	    changecolor("MENU:\r\n", WHITE);
    	    changecolor("(A). Chat Server (I want someone to connect to me)\r\n", LIGHTBLUE);
    	    changecolor("(B). Chat Client (I want to choose someone to talk to)\r\n", LIGHTBLUE);
    	    changecolor("CHOICE: ", LIGHTGREEN);
    	    cin >> abc;
    		
    	    switch(toupper(abc)){       
    		
    	         case 'A':
    	            chat_server(MySocket, contin);         //you will wait for someone to connect to you
    	            break;
    	
    	         case 'B':
    	         	chat_client(MySocket, contin);       //you get to choose someone to speak to
    	            break;
    				
    			case 'C':
    				//insert IP and hostname output here
    	
    	         default:	 
    			 	cout << "I don't understand\n";	   
    	      }
    	
    	}while(contin);
    
    
        WSACleanup();   // Shutdown Winsock
        getch();
    	return 0;
    }
    
    
    void start_winsock(WSADATA& data){
    	if(WSAStartup(WINSOCK_VERSION,&data) != 0){        //begins Winsock, but exits if there is initialiation error
           cout << "ERROR!! Windows sockets were unable to initialize.\n" 
    	        << "WSAStartup did not return a 0, something is amiss...\n";
           getch();
           exit(1);
        }
    
    } //end void start_winsock
    
    
    void output_winsock_data(WSADATA data){
    	cout << "Windows sockets initialized" << endl << endl;
        cout << "WSAStartup data returned: " << endl;
        slowtype("wVersion: ");
    	cout << data.wVersion << endl;
        slowtype("wHighVersion: ");
    	cout << data.wHighVersion << endl;
        cout << setbase(10);
    	slowtype("szDescription: ");
    	cout << data.szDescription << endl;
        slowtype("szSystemStatus: ");
    	cout << data.szSystemStatus << endl;
    } //end void output_winsock_data
    
    
    void open_socket(SOCKET& MySocket){
    	MySocket = socket(AF_INET, SOCK_STREAM, 0);   // Go over TCP/IP, socket type, protocol
    	//IPPROTO_TCP
        if (MySocket == INVALID_SOCKET) {                   //unable to open socket
    		printf("Error, socket() unabled to be opened");
    		getch();
    		WSACleanup();   //End Winsock
    		exit(1);
    	}
    	
    } //end void open_socket
    
    
    void chat_server(SOCKET& MySocket, bool& contin){
    	SOCKET theClient;      //used for incoming connection socket
        SOCKADDR_IN bindToAddress;     // Use SOCKADDR_IN to fill in address information
        SOCKADDR_IN fromAddress;
        char incoming[MAX_LEN];
        char outgoing[MAX_LEN];
        char charnum[30];
        int length = sizeof(fromAddress);
        bindToAddress.sin_family = AF_INET;
        bindToAddress.sin_port = htons(PORT);       //converts for the port field in correct byte order
        bindToAddress.sin_addr.s_addr = INADDR_ANY;  // Since this is a server, any address will do
        bind_socket(MySocket, bindToAddress);
    
        listen_on_stream_socket(MySocket);
    	clrscr();
        changecolor("Listening for a connection from TCP port ", LIGHTGREEN);
    	sprintf(charnum, "%d", PORT); //word used as buffer
    	changecolor(charnum, WHITE);
    	  
    	cout << "...\n-----------------------------------------------" << endl;
    	  
    	accept_msg_socket(MySocket, theClient, fromAddress, length);
    	clrscr();
        changecolor(inet_ntoa(fromAddress.sin_addr), LIGHTGREEN);
    	cout << " has connected to you. Chatting...\n\n\n";
        
    	flushin();
    	
       	do{
    		changecolor("Wait for reply...\r\n", LIGHTGREEN);
            receive_message(theClient, incoming);
    
            changecolor(inet_ntoa(fromAddress.sin_addr), LIGHTRED);
    		changecolor(": ", LIGHTRED);
    		changecolor(incoming, WHITE);
            cout << endl;
    		
            changecolor("Your message: ", LIGHTBLUE);
            cin.getline(outgoing, MAX_LEN);
    
    
            send_reply(theClient, outgoing);
    	} while(1);
    
    } //end void chat_server
    
    
    void chat_client(SOCKET& MySocket, bool& contin){
    	SOCKADDR_IN remoteAddress;   
        hostent* host;
        u_long machineIP;     
    	char Server[MAX_LEN];
        char incoming[MAX_LEN];
        char outgoing[MAX_LEN];
    	int address;
    
        clrscr();
        cout << "Type an IP Address or Hostname to connect to" << endl;
        cin >> Server;
        cout << endl;
    	
        find_host(Server, host, address, remoteAddress);
    	connect_host(MySocket, remoteAddress);
    	flushin();
    	
        do{
    		changecolor("Your Message: ", LIGHTBLUE);
    
            cin.getline(outgoing, MAX_LEN);
            send_reply(MySocket, outgoing);
    		changecolor("Wait for reply...\r\n", LIGHTGREEN);
    		receive_message(MySocket, incoming);   
            changecolor(inet_ntoa(remoteAddress.sin_addr), LIGHTRED);
    		changecolor(": ", LIGHTRED);
            changecolor(incoming, WHITE);
    		cout << endl;  
    	}while(1);   //run forever
    
    } //end void chat_client
    
    
    void bind_socket(SOCKET& MySocket, SOCKADDR_IN& bindToAddress){
    
    	if(bind(MySocket, (struct sockaddr*)&bindToAddress, sizeof(bindToAddress)) == SOCKET_ERROR){  //binds socket
             cout << "Error binding socket" << endl;    //if it can't cast sockaddr_in to sockaddr*, exit
             getch();
             WSACleanup();
             exit(1);
          }
    	  
    } //end void bind_socket
    
    
    void listen_on_stream_socket(SOCKET& MySocket){
    
    	if (listen(MySocket,5) == SOCKET_ERROR){     //5 is the number of clients that can be queued
             cout << "Error listening on socket" << endl;
             getch();
             WSACleanup();
             exit(1);
          }
    	  
    } //end void listen_on_stream_socket
    
    
    void accept_msg_socket(SOCKET& MySocket, SOCKET& theClient, SOCKADDR_IN& fromAddress, int& length){
    	theClient = accept(MySocket,(struct sockaddr*)&fromAddress, &length); 
    	  //server Socket, Address sockaddr structure, Address var containing size of sockaddr
    	  
        if (theClient == INVALID_SOCKET){
        	cout << "Error accepting connection on message socket!!" << endl;
            getch();
            WSACleanup();
            exit(1);
        }
    	
    } //end void accept_msg_socket
    
    
    void receive_message(SOCKET& Socket, char incoming[MAX_LEN]){
    
    	if(recv(Socket,incoming,sizeof(incoming), 0) == SOCKET_ERROR){ //Connected socket, receive buffer, no flags
            cout << "Error receiving data from message socket into buffer!" << endl;
        	getch();
            WSACleanup();
            exit(1);
        }
    	
    } //end void receive_message
    
    
    void find_host(char Server[MAX_LEN], hostent* host, int& address, SOCKADDR_IN& remoteAddress){
    
    	if (isalpha(Server[0]))        //Server IP is a hostname because it's in English letters
           host = gethostbyname(Server);   //gets the host by the name of the server
    	   
        else{ //Server is an IP Address, must be numbers
           address = inet_addr(Server);   // convert address and lookup hostname
           host = gethostbyaddr((char *)&address,sizeof(address),AF_INET);
        }
    	
        if (host == NULL ){   //you entered nothing? You fool.
           cout << "Cannot resolve address " << Server << endl;
    	   getch();
           WSACleanup();
           exit(1);
        }
    	
    	remoteAddress.sin_family = AF_INET;   
        remoteAddress.sin_port = htons(PORT); 
    
        if (host!=NULL){         //the host exists
           memcpy(&(remoteAddress.sin_addr),host -> h_addr,host -> h_length);       //store address
           cout << "Found " << Server << " without any errors." << endl
    	        << "IP Address:   " << inet_ntoa(remoteAddress.sin_addr) << endl
                << "Hostname:   " << host -> h_name << endl;
        }
    
    } //end void find_host
     
    
    void connect_host(SOCKET& MySocket, SOCKADDR_IN& remoteAddress){
    	cout << "\nAbout to connect to " << inet_ntoa(remoteAddress.sin_addr) << "... press a key." << endl;
        getch();
    	
    	if(connect(MySocket,(struct sockaddr*)&remoteAddress, sizeof(remoteAddress)) == SOCKET_ERROR){
             cout << "The connection was a complete and utter failure, too bad!" << endl;
             getch();
             WSACleanup();
             exit(1);
         }
    	 
         cout << "Connected with ";
    	 changecolor(inet_ntoa(remoteAddress.sin_addr), LIGHTGREEN);
    	 cout << "...\n---------------------------------------------\n\n";
    } //end void connect_host
    
    
    void send_reply(SOCKET& Socket, char outgoing[MAX_LEN]){
    
    	if(send(Socket,outgoing,sizeof(outgoing),0) == SOCKET_ERROR){
            cout << "Error sending reply" << endl;
            getch();
            WSACleanup();
            exit(1);
       }
       
    } //end void send_reply
    
    
    void changecolor(char* word, int color){
    	textcolor(color); 		 //changes text to the color given through the argument
    	cprintf("%s", word);	 //outputs the string in the given color
    	textcolor(LIGHTGRAY);	 //change color back to the default light gray
    } //end void changecolor
    
    
    void slowtype(char* word){
    
    	for (int i = 0; word[i] != '\0'; i++){
    		cout << word[i];
    		Sleep(70);
    	}  //outputs text slowly
    	
    	Sleep(30);
    		   
    } //end void slowtype
    
    
    void flushin(){
    	
    	while (cin.get() != '\n'){}
    	
    }
    It all works except for that damn output from the other user. What is going wrong!?

  2. #2
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    It would also be useful to know how to output your OWN IP and hostname, if anyone is willing to help there

  3. #3
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    I think I posted too much code. Someone is either going to leech it or ignore it.


    Arugh, again, if anyone is willing to take the time to read this whole thing I'll have to repay them somehow... I don't know what yet

  4. #4
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    Hmmm perhaps I should have been more specific

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >>sizeof(incoming)

    This will be 4.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    OHHH!!!! THANK YOU!!!

  7. #7
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    *kisses feet* I am forever in your gratitude!@!!!

  8. #8
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    You also wouldn't happen to know how to output your own IP and hostname would you?

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Anyway, just remember that a local array (but not local dynamically alloc'ed ones) will return the correct array sizeof. Passed into a function, it is treated as a (const) pointer, which is 4 bytes on most machines. And kiss Salems feet. He was who pointed it out to me long ago...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    TiMMiT
    Guest
    Nakeerb, do you happen to know anything about using proxies with winsock?

    --Tim

  11. #11
    Registered User
    Join Date
    Oct 2002
    Posts
    155
    Not at all, really. I was barely able to get this working. I still need to output the IP and hostname

  12. #12
    Mmm. Purple.
    Join Date
    May 2002
    Posts
    154

    IPCONFIG

    Old dos tool that give ip maybe u can do sumthing with it (i doubt it very much but its it uses a dll it may help)

  13. #13
    getting your IP:

    Use these:
    int gethostname(char *hostname, size_t size);
    struct hostent *gethostbyname(const char *name);

    like this:
    Code:
    char hostname[256];
    gethostname(hostname, (size_t)256);
    hostent host = gethostbyname(hostname)
    then you use the hostent struct:

    Code:
    struct hostent {
            char    *h_name;
            char    **h_aliases;
            int     h_addrtype;
            int     h_length;
            char    **h_addr_list;
        };
        #define h_addr h_addr_list[0]
    then you do this to get the IP address:
    Code:
    inet_ntoa(*((struct in_addr *)h->h_addr)
    Last edited by Inquirer; 10-22-2002 at 08:43 PM.
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

  14. #14
    hmmmm...

    sry about that, i musn't have seen that the qustion was already answered.
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 07-05-2004, 07:41 PM
  2. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  3. C Chat program
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 03-30-2002, 06:39 AM
  4. simple chat program
    By ender in forum C++ Programming
    Replies: 1
    Last Post: 11-12-2001, 11:48 PM
  5. Ghost in the CD Drive
    By Natase in forum A Brief History of Cprogramming.com
    Replies: 17
    Last Post: 10-12-2001, 05:38 PM