| | |
strange signs server->client connection with select()
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
•
•
Join Date: Jan 2009
Posts: 3
Reputation:
Solved Threads: 0
hi there,
like almost everybody else here i've got a problem.
I am working on a simplified IRC for unix, consisting of a server and a client. It's a task for university..
my problem is, my client receives strange signs from the server and when i want to parse them there are lots of more strange signs! I think the problem is that i dont convert strings and chars correctly or something in my assignments is wrong, but what?! Or maybe i got a logical problem with my STDIN_FILENO and select().
now here's the code for you gurus and experts out there, willing to help a poor student that has learned Java and is collecting his first experiences in C++.
here are is a part of the code, please dont be scared if it looks a bit long.
as a short description:
first i create my object client, then i create the sockets and after that i send/receive whatever select() is expecting. i got parts from the code from examples that i found in the www, trying to adapt them to my needs.
If you have any further questions, dont hesitate to ask me.
best regards
cylow22
like almost everybody else here i've got a problem.
I am working on a simplified IRC for unix, consisting of a server and a client. It's a task for university..
my problem is, my client receives strange signs from the server and when i want to parse them there are lots of more strange signs! I think the problem is that i dont convert strings and chars correctly or something in my assignments is wrong, but what?! Or maybe i got a logical problem with my STDIN_FILENO and select().
now here's the code for you gurus and experts out there, willing to help a poor student that has learned Java and is collecting his first experiences in C++.
here are is a part of the code, please dont be scared if it looks a bit long.
as a short description:
first i create my object client, then i create the sockets and after that i send/receive whatever select() is expecting. i got parts from the code from examples that i found in the www, trying to adapt them to my needs.
If you have any further questions, dont hesitate to ask me.
best regards
cylow22
C++ Syntax (Toggle Plain Text)
#include "client.h" using namespace std; client::client(string hostname, string port, string nickname) { this-> hostname = hostname; this-> port = port; this->nickname= nickname; topic=""; startClient(hostname, port); } int client::startClient(string hostname, string port) { const char *host; const char *service; service = port.c_str(); host = hostname.c_str(); int error; struct addrinfo hints; struct addrinfo *addr0; memset(&hints, 0, sizeof(hints)); //hints.ai_family = PF_UNSPEC; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = 0; printf("Looking up host.."); if ((error = getaddrinfo(host, service, &hints, &addr0)) < 0) { perror(gai_strerror(error)); return 1; } printf(" OK \n"); int sockno; struct addrinfo *addr; for (addr = addr0; addr; addr = addr->ai_next) { printf("Creating socket (ai_family=%d, ai_socktype=%d, ai_protocol=%d)...\n", addr->ai_family, addr->ai_socktype, addr->ai_protocol ); if ((sockno = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0) { perror("socket"); continue; } printf(" OK \n"); printf("Connecting to host..."); if ((connect(sockno, addr->ai_addr, addr->ai_addrlen)) < 0) { perror("connect"); close(sockno); continue; } break; } if (!addr) { printf("No connection found\n"); return 1; } printf(" OK \n"); freeaddrinfo(addr0); bool first_login = true; std::string input; std::string cmd; fd_set read_set0; FD_ZERO(&read_set0); FD_SET(STDIN_FILENO, &read_set0); FD_SET(sockno, &read_set0); do { char buffer[1024]; int res; ssize_t length; //int length; fd_set read_set = read_set0; if ((res = select(sockno + 1, &read_set, NULL, NULL, NULL)) > 0) { /* // auto-login isn't working yet if (first_login==true) { string logincmd = "/LOGIN "; cmd = getCommand(logincmd).c_str(); cout<<"getCommand liefert: "<<cmd<<endl; strcpy(buffer, cmd.c_str()); first_login = false; } else { */ if (FD_ISSET(STDIN_FILENO, &read_set)) { printf("Read STDIN...\n"); if ((length = read(STDIN_FILENO, buffer, sizeof(buffer))) < 0) { perror("read"); continue; } //input = buffer; cmd = getCommand(buffer).c_str(); cout<<"cmd: "<<cmd<<endl; strcpy( buffer, cmd.c_str()); cout<<"buffer: "<<buffer<<endl; buffer[length]='\0'; //strcpy( buffer, input.c_str()); } printf("Write socket...\n"); buffer[length]='\0'; if ((length = write(sockno, buffer, length)) < 0) { perror("write"); continue; } //} if (FD_ISSET(sockno, &read_set)) { printf("Read socket...\n"); if ((length = read(sockno, buffer, sizeof(buffer))) < 0) { perror("read"); continue; cout<<"length: "<<length<<endl; } else if (length == 0) { printf("Server closed connection\n"); break; } printf("Write STDOUT...\n"); if ((length = write(STDOUT_FILENO, buffer, length)) < 0) { perror("write"); continue; } buffer[length]='\0'; std::string tmp = buffer; cout<<handleServerMessage(tmp)<<endl; //cout<<"inc_buffer: "<<buffer<<endl; } } else if (res < 0 && errno == EINTR) { continue; } else { perror("select"); return 1; } } while (1); close(sockno); return 0; } std::string client::getCommand(string message) { int msg_length = message.find(' ', 0); std::string command = message.substr(0, msg_length); int channel_msg_length = message.find('/', 0); std::string oldname; std::string oldtopic; std::string cmd_code; if ((command == "/JOIN" || command == "/join") && message.size() > 6) { channel = message.substr(msg_length+1, MAXCHANNELNAME); cout<<"You are in channel "<<channel<<'.'<<endl<<flush; cmd_code ="10101"; cmd_code+=channel; return cmd_code; } else if (((command == "/LOGIN") || (command == "/login")) && message.size() > 6) { cmd_code ="10001"; cout<<nickname<<endl; cmd_code+=nickname; cout<<cmd_code<<endl; return cmd_code; } else { cmd_code ="10011"; cmd_code+=topic; cout<<cmd_code<<endl; return cmd_code; } } else if((channel_msg_length==-1)) { cmd_code="10111"; cmd_code+=message; return cmd_code; } } std::string client::handleServerMessage(string message) { std::string header=message.substr(0, 5); int server_msg_length = message.length(); std::string modified_msg; if (header == "10111") { modified_msg = message.substr(5, server_msg_length); return modified_msg; } else if (header == "10101") { std::string temp = ("You are in channel "); temp += modified_msg; temp += '.'; return temp; } }
If you look at
You're reading characters into a buffer and then converting that to a string, and then _later_ putting a null character to mark the end of the inputted characters. Think about what that means.
You might have similar problems in other locations in your code.
C++ Syntax (Toggle Plain Text)
if ((length = read(STDIN_FILENO, buffer, sizeof(buffer))) < 0) { perror("read"); continue; } cmd = getCommand(buffer).c_str(); cout<<"cmd: "<<cmd<<endl; strcpy( buffer, cmd.c_str()); cout<<"buffer: "<<buffer<<endl; buffer[length]='\0';
You're reading characters into a buffer and then converting that to a string, and then _later_ putting a null character to mark the end of the inputted characters. Think about what that means.
You might have similar problems in other locations in your code.
•
•
Join Date: Jan 2009
Posts: 3
Reputation:
Solved Threads: 0
hey rashakil,
i am sorry because i dont know what that means. i am not sure if I have to add the '\0' to the char array buffer or to a string. how does the '\0' really work?
here is my client.h:
i am sorry because i dont know what that means. i am not sure if I have to add the '\0' to the char array buffer or to a string. how does the '\0' really work?
here is my client.h:
•
•
•
•
#ifndef CLIENT_H_
#define CLIENT_H_
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#define BUF_SIZE 1024
#define SERVER "The_server_name_or_IP"
#define SERVERPORT 5001
#define MAXCHANNELNAME 12
#define MAXNICKSIZE 9
#define MAXTOPICSIZE 12
#define MAX_MSG_SIZE 140
using namespace std;
class client {
public:
client(string, string, string);
int startClient(string, string);
std::string getCommand(string);
std::string handleServerMessage(string);
string hostname;
string nickname;
string topic;
string port;
private:
int msg_length;
int channel_msg_length;
std::string oldname;
std::string oldtopic;
std::string cmd_code;
std::string channel;
std::string cmd;
};
#endif /*CLIENT_H_*/
A char* points to an array of characters (or maybe a single character, of course, but typically an array). You know how arrays work, I presume.
The function 'read' will fill the array with some number of characters (that have been read off the input stream).
Suppose your array contains the following before the read operation:
These are just arbitrary characters, but in particular you'll see a nul character at position 12. It's not the character '0', which has value 48 -- it's the character with value 0. C-style strings are character arrays with a 0 at the end. For example, if you wanted to find the length of a C-style string, you might use a function written as follows:
If you passed the address of the array I drew to this function, you would get 12.
Now let's look at how 'read' works. Suppose 'read' detects 7 characters, the word "Helllo!", at the input stream. So it returns 7 and writes those characters to the array whose address was passed as a parameter.
Our array (if we passed it to 'read') now looks like this:
But as far as string functions are concerned, the 'string' contains 12 characters. For example, if you passed a char* to the std::string constructor, you would get a string with 12 characters. The std::string constructor reads characters until it comes across a character with the value 0.
If we look at your code again, we'll see that you have
If you wrote
The function 'read' will fill the array with some number of characters (that have been read off the input stream).
Suppose your array contains the following before the read operation:
C++ Syntax (Toggle Plain Text)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| '#' '$' '%' 'T' '2' '5' '9' '&' 'H' 't' '_' '^' 0 'k' 'l' 'a'
C++ Syntax (Toggle Plain Text)
int strlen(char* s) { int i = 0; while (s[i] != 0) i++; return i; }
Now let's look at how 'read' works. Suppose 'read' detects 7 characters, the word "Helllo!", at the input stream. So it returns 7 and writes those characters to the array whose address was passed as a parameter.
Our array (if we passed it to 'read') now looks like this:
C++ Syntax (Toggle Plain Text)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| 'H' 'e' 'l' 'l' 'l' 'o' '!' '&' 'H' 't' '_' '^' 0 'k' 'l' 'a'
If we look at your code again, we'll see that you have
cmd = getCommand(buffer).c_str(); immediately after the read operation. You'll note that getCommand expects a std::string. C++ does an automatic conversion, then, from the C-style string to the std::string. So getCommand would receive a string with 12 characters, "Hello!&Ht_^".If you wrote
buffer[length] = '\0' immediately after the read operation, the string conversion would stop at the end of the characters you've input. •
•
Join Date: Jan 2009
Posts: 3
Reputation:
Solved Threads: 0
thanks for the reply rashakil, that helped me a bit. but my problem is, that I use read to get the userinput from keyboard and after that, check the input and want to send a header and behind this header, i want to add the message or something. for example if you want to send a simple "hello" message in a channel the getCommand converts the input to "10111hello". my problem is that the length of the char array is no constant at all. so the ssize_t length has to be 10 in this case to allow me to use buffer[10]='\0'. do you understand my problem?
![]() |
Other Threads in the C++ Forum
- Previous Thread: Confused
- Next Thread: question on c++ programing
| Thread Tools | Search this Thread |
api array based binary bitmap c++ c/c++ calculator char char* class classes code coding compile console conversion count database delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp iamthwee ifstream input int java lib linkedlist linker linux list loop looping loops map math matrix memory multiple news node number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg sorting string strings temperature template templates test text text-file tree unix url variable vector video visualstudio win32 windows winsock word wordfrequency wxwidgets






