I have this code for verify what's in the array buffer, but i'm always getting different values on array and it makes my program getting a 56( 8 on ascii) when its not supose too, can somebody helps ?
This sends a buffer for socket to be read on file 1:
void send_stream(char buff[], int sockfdes)
{
if (write(sockfdes, buff, strlen(buff) + 1) == -1) {
perror("ERROR: envia_stream: simulador");
}
}
void prepare_message(int tipo, int id)
{
char buff[3];
buff[1] = id;
switch (tipo)
{
case CRIACAO_P:
buff[0] = '1';
//buff[2] = tempo; //HORA
send_stream(buff, sockfd);
break;
}
this file 2 read from socket and put in buffer:
char buffer[5];
while(1)
{
read(novosockfd, buffer, sizeof(buffer));
if (buffer[0] == '8')//FIM
{
printf("Buffer[0]: %d \n", buffer[0]);
printf("Buffer[1]: %d \n", buffer[1]);
printf("Buffer[2]: %d \n", buffer[2]);
printf("Buffer[3]: %d \n", buffer[3]);
printf("Buffer[4]: %d \n", buffer[4]);
printf("\nSimulação terminou\n");
break;
}
}
}
firstly you should tell us from where are you reading from, if you are reading from a socket, trying to implement a server or are you reading from a local socket?
Also, you should also check for the return type, like this:
if ( (read(novosockfd, buffer, sizeof(buffer)) <= 0 ) {
perror("error in read");
} else
{
//code to run if the read did not failed;
}
Note that for perror to work you have to #include
perror will automatically print the message in "" followed by the error description in the console. After you do all this, come and tell us more details.
Take not that if you do not check for failure in read, your code continues to get executed.
Judging by your update, you are first writing a buffer of size 4 bytes and reading for a buffer of 5 bytes, note that reading from a socket blocks until receiving the specified size in buffer, hence if you send 4 bytes to that socket, you can't expect to be able to read 5 bytes. So in order to be able to send the message, you should have char buff[4] declared in preare_message() instead of char buff[3], and also the parameter for the size of the message in the method write(int fildes, const void *buf, size_t nbytes) is of type size_t, so you should use : write(sockfdes, buff, sizeof(char) * strlen(buffer) + 1);
And you are also assigning id(int) into a char buffer.
Related
I'm writing a simple text-based protocol interpreter for server. The server will receive a response in the format of METHOD [filename]\n[file_size][data] from socket, where the string length of METHOD, filename, and data vary. file_size is the number of bytes of data. Since the length of METHOD and filename vary, I try to use fscanf() to capture them. After that, I use read() to get file_size and data. However, the problem is read() never prints. I wrote a small case to illustrate my problem:
#define MSGSIZE 16
char* msg1 = "hello world\n#1";
int main()
{
char inbuf[MSGSIZE], *buf_1, *buf_2;
int p[2], i;
if (pipe(p) < 0)
exit(1);
write(p[1], msg1, MSGSIZE);
FILE *fd = fdopen(p[0], "r");
fscanf(fd, "%ms %ms\n", &buf_1, &buf_2);
printf("buf_1: %s, buf_2: %s\n", buf_1, buf_2);
// read never prints
read(fileno(fd), inbuf, 3);
printf("buf: %s\n", inbuf);
return 0;
}
I would expect fscanf() to move the character pointer to '#' in "hello world\n#1", then read should be able to print out following characters, which didn't happen. I'm a bit confused because if I call fscanf() instead of read, it would print. Is this because fscanf() manipulates file indicator differently from read()?
You should not mix operations on the FILE * with operations on the underlying file descriptor. If you just replace read with an fread, it should behave as you expect. The fscanf (probably, almost certainly) reads everything from the pipe and stores it in an internal buffer, so your read has no data left to consume. To access the internal buffer, use fread or fgetc or fgets, but don't try to work on the underlying file descriptor.
Mixing FILE* stream I/O with system calls on the underlying file descriptor is the problem. Here is a change I made that shows one way to avoid it in your code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MSGSIZE 16
char* msg1 = "hello world\n#1\n";
int main()
{
char inbuf[MSGSIZE], *buf_1, *buf_2;
int p[2], i;
if (pipe(p) < 0)
exit(1);
write(p[1], msg1, MSGSIZE);
FILE *fd = fdopen(p[0], "r");
fscanf(fd, "%ms %ms\n", &buf_1, &buf_2);
printf("buf_1: %s, buf_2: %s\n", buf_1, buf_2);
// read never prints
//retVal = read(fileno(fd), inbuf, 3);
// replace read() with fgets()
if(fgets(inbuf, sizeof(inbuf), fd) == NULL)
{
printf("Error with fgets()\n");
}
else
{
printf("buf: %s\n", inbuf);
}
return 0;
}
I'm programming in C an IRC chat client. everything it's working well except I can't read the whole answer sent by the server. here's the code:
char buffer[2048];
write_on_screen(current_page(), "LOG COMMAND", command);
write(sockfd, command, strlen(command)); //write to socket
bzero(buffer, sizeof(buffer));
read(sockfd, buffer, sizeof(buffer));
write_on_screen(current_page(), "RESPONSE", buffer);
return buffer;
most of the time buffer will contain just a piece of the response (which is shorter than 2048 bytes) and other times it contains nothing. in both cases if I do another read() after the first one, it returns me the rest of the answer or another small piece (and then I've to do another read() again). if I put a sleep(1) between write() and read() I get the whole answer, but I'm sure this not a good pratice.
Is there some way I can avoid this?
thank you in advance
You're making the usual mistakes. It is impossible to write correct network code without storing the result of read() or recv() into a variable. You have to:
Check it for -1, and if so look at errno to see whether was fatal, which it almost always is except for EAGAIN/EWOULDBLOCK, and if fatal close the socket and abandon the process.
Check it for zero, which means the peer disconnected. Again you must close the socket and abandon the process.
Use it as the count of bytes actually received. These functions are not obliged nor guaranteed to fill the buffer. Their contract in blocking mode is that they block until an error, end of stream, or at least one byte is transferred. If you're expecting more than one byte, you normally have to loop until you get it.
According to RFC-1459, a single line of text in IRC can contain up to 512 characters and is terminated by a CRLF (\r\n) pair. However:
You're not guaranteed to receive exactly 512 bytes each time. For example, you might receive a comparatively short message from someone else one in the channel: Hi!
Related to the above: A group of 512 bytes might represent more than one message. For example, the buffer might contain a whole line, plus part of the next line: PRIVMSG <msgtarget> <message>\r\nPRIVMS
Given that you could have zero-or-more complete lines plus zero-or-one incomplete lines in your buffer[] at any time, you could try doing something along the lines of:
char buffer[2048];
while(keep_going)
{
char **lines;
int i, num_lines;
// Receive data from the internet.
receiveData(buffer);
// Create an array of all COMPLETE lines in the buffer (split on \r\n).
lines = getCompleteLines(buffer, &num_lines);
removeCompleteLinesFromBuffer(buffer);
// Handle each COMPLETE line in the array.
for (i = 0; i < num_lines; ++i) { handle_line(lines[i]); }
freeLines(lines);
}
This would allow you to handle zero or more complete lines in one go, with any incomplete line (i.e anything after the final \r\n pair) being kept around until the next call to receiveData().
You need to loop around read() until a CRLF had been detected.
A possible way to do this would be:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
ssize_t read_until_crlf(int sd, char * p, size_t s, int break_on_interupt)
{
ssize_t bytes_read = 0;
ssize_t result = 0;
int read_cr = 0;
int read_crlf = 0;
while (bytes_read < s)
{
result = read(sd, p + bytes_read, 1);
if (-1 == result)
{
if ((EAGAIN == errno) || (EWOULDBLOCK == errno))
{
continue;
}
else if (EINTR == errno)
{
if (break_on_interupt)
{
break;
}
continue;
}
else
{
perror("read() failed");
break;
}
}
else if (0 == result)
{
break; /* peer disconnected */
}
if ('\r' == p[bytes_read])
{
read_cr = 1;
}
else if (('\n' == p[bytes_read]) && read_cr)
{
read_crlf = 1;
break; /* CRLF detected */
}
else
{
read_cr = 0;
}
++bytes_read;
}
if (!read_crlf)
{
result = -1; /* Buffer full without having read a CRLF. */
errno = ENOSPC; /* ... or whatever might suite. */
}
return (0 >= result) ?result :bytes_read;
}
Call it like this:
#include <stdio.h>
ssize_t read_until_crlf(int sd, char * p, size_t s, int break_on_interupt);
int main(void)
{
int sd = -1;
/* init sd here */
{
char line[2048] = "";
ssize_t result = read_until_crlf(sd, line, sizeof line, 0);
if (-1 == result)
{
perror("read_until_newline() failed");
}
printf("read '%s'\n", line);
}
return 0;
}
I'm trying to implement a working HTTP Client-Server application just to make practice with network programming.
The 2 programs have to follow this basic algorithm:
CLIENT - send a GET request
SERVER - send "+OK\r\n"
SERVER - send file size in bytes
SERVER - send file
CLIENT - send ACK
I'm having a lot of troubles in the reading part, probably because i perform some dirty read on the stream.
These are the 2 reading function that i'm using:
/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read*/
int readline (SOCKET s, char *ptr, size_t maxlen)
{
size_t n;
ssize_t nread;
char c;
for (n=1; n<maxlen; n++)
{
nread=recv(s, &c, 1, 0);
if (nread == 1)
{
*ptr++ = c;
if (c == '\n')
break;
}
else if (nread == 0) /* connection closed by party */
{
*ptr = 0;
return (n-1);
}
else /* error */
return (-1);
}
*ptr = 0;
return (n);
}
and:
int readNumber(SOCKET s, long *num, int maxRead)
{
size_t n;
ssize_t nread;
int totRead;
long number=0;
for (n=1; n<maxRead+1; n++)
{
nread=recv(s, &number, sizeof(number), 0);
if (nread == sizeof(number))
{
totRead+=nread;
*num = number;
}
else if (nread == 0) /* connection closed by party */
{
*num = 0;
return (n-1);
}
else /* error */
{
printf("nread = %d\n", nread);
return (-1);
}
}
return (totRead);
}
this is the snippet of the main where i receive the +OK message and then the file size:
memset(rbuf,0,sizeof(rbuf)); //rbuf is the buffer where is store the read
printf("waiting for response...\n");
result = readline(s, rbuf, sizeof(rbuf)); //reading function is above
printf("Byte read(okMsg) = %d\n", result);
if (result <= 0)
//ERROR MANAGEMENT
{
printf("Read error/Connection closed\n");
closesocket(s);
SockCleanup();
exit(1);
}
else
{
long fileLength=0;
unsigned char *fBuf;
//RECEIVE OK
if(!strcmp(rbuf,"+OK\r\n"))
{
puts("+OK\n");
//RECEIVE FILE LEN
int nw = readNumber(s, &fileLength, 1); //reading function is above
printf("Byte read(fDim) = %d\n", nw);
printf("File is %ld bytes long\n", fileLength);
if(nw >0)
{
// RECEIVE FILE
}
}
}
When i send the "+OK\r\n" string the server tells me that it sends 8 bytes, but when i read i find the '\0' char only after 6 bytes.
By the way it reads correctly the message, but when i try to read the file size (that is a long) it gives me back a wrong number.
My opinion is that the stream buffer is dirty, and that i'm reading 2 bytes that are not part of the file size, but i'm not understanding why this happens.
Please ask me more info if i'm not clear enough.
SOLVED:
Thank you all for your answers!!!
You put me in the right mindset to understand what was wrong.
Look like the problem was this declaration in the server:
char *okMsg = "+OK\r\n";
instead of
char okMsg[] = "+OK\r\n";
that lead me to an undefined behavior.
long number=0;
for (n=1; n<maxRead+1; n++)
{
nread=recv(s, &number, sizeof(number), 0);
You forgot to design and implement a protocol to carry the data between your server and your client. Because TCP provides a stream of bytes, your protocol should be defined as a stream of bytes.
How many bytes convey this number? Is "however many bytes a 'long' happens to occupy on my platform" a good answer? What's the semantic meaning of the first byte? Is "whatever the first byte of a 'long' happens to mean on my platform" a good answer?
A good answer would be, "The size shall be conveyed as a 4-byte unsigned integer in little-endian byte order". Then make absolutely sure your code sends and receives in that format.
In C, I ask the server to print the content of any messages that it receives. All messages follow the format: "Message: /counter/".
while (1){
length = sizeof(struct sockaddr);
/* receive from client */
lenstr = recv(newfd, buff, 20000, 0);
if (lenstr == -1){
perror("recv(): ");
exit(1);
}
buff[lenstr] = '\0';
printf("Received: %s \n", buff);
/* send back to client*/
if (send(newfd, buff, lenstr, 0) < 0){
perror("send(): ");
exit(-1);
}
When I run the server, messages appear one after the other, without going to the new line. What am I missing here? (connection is TCP here)
Thanks.
The data it receives from the socket may contain zeroes or control characters. These should not be printed.
Try using the following function to dump received data into stdout. It replaces all non-printable characters with a dot:
void dump_buf(char const* buf, size_t buf_len) {
char const* buf_end = buf + buf_len;
while(buf != buf_end) {
char c = *buf++;
putchar(isprint(c) ? c : '.');
}
putchar('\n');
}
// ...
lenstr = recv(newfd, buff, 20000, 0);
if (lenstr == -1) {
perror("recv(): ");
exit(1);
}
dump_buf(buff, lenstr);
TCP doesn't have "messages", it handles continuous byte streams in both directions. You are just reading whatever is less between the received data up to that instant and your 2000. Perhaps you really want Stream Control Transmission Protocol? Or mark message ends in some way (perhaps by '\n'), and read character by character? Or just read the length of a single message (if they are fixed length, that is)?
I have written a small code using pipe and fork. The child process calls child function which writes to the pipe. The parent process calls parent function which reads from the pipe.
The problem comes when the first call of the program after fork() goes to parent function. Here the write end is closed. Now the problem is that the read call is reading some garbage into buf and nread is giving value > 0 . How can this be prevented.
Using Linux 2.6.32-30-generic and gcc 4.4.3. Below is the code::
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define MSGSIZE 16
void parent(int* p);
void child(int* p);
char* msg1 = "hello";
char* msg2 = "bye";
int main()
{
int pfd[2];
if(pipe(pfd) == -1)
{
printf("Unable to create pipe\n");
exit(1);
}
fcntl(pfd[0],F_SETFL,O_NDELAY);
if(fork() == 0)
child(pfd);
else
parent(pfd);
return 0;
}
void parent(int p[2])
{
int nread;
char buf[MSGSIZE];
buf[0] = '\0';
close(p[1]);
for(;;)
{
nread = read(p[0] , buf , MSGSIZE);
if(nread == 0)
{
printf("pipe Empty/n");
sleep(1);
}
else
{
if(strcmp(buf,msg2) == 0)
{
printf("End of conversation\n");
exit(0);
}
else
printf("MSG=%s\n" , buf);
}
}
}
void child(int p[2])
{
int count;
close(p[0]);
for(count = 0 ; count < 3 ; count++)
{
write(p[1],msg1 , MSGSIZE);
sleep(3);
}
write(p[1],msg2,MSGSIZE);
exit(0);
}
One problem is this:
char buf[MSGSIZE];
buf[0] = '\0';
this only sets the first character in buf to the null terminator: the remaining characters in buf are unitialized. The read() is attempting to read 16 bytes meaning the characters in buf will not be null terminated and printf("%s", buf) requires that buf is null terminated. Even if buf had been initialized correctly it would still not be sufficient due to its size being 16 but the read() reading 16 also, leaving no room for the null terminator.
A possible fix would be:
char buf[MSGSIZE + 1] = ""; /* +1 added to store the null terminator and
all characters set to 0 (null terminator). */
Another problem is the write()s (as commented by Joachim Pileborg):
write(p[1],msg1 , MSGSIZE);
write(p[1],msg2 , MSGSIZE);
msg1 and msg2 are not 16 bytes long. Change to:
write(p[1],msg1 , strlen(msg1));
write(p[1],msg2 , strlen(msg2));
Also, read() returns -1 on failure so the following is not sufficient:
nread = read(p[0] , buf , MSGSIZE);
if(nread == 0)
{
...
}
Check also for -1:
else if(nread == -1)
{
fprintf(stderr, "read() failed: %s\n", strerror(errno));
}
else
{
...
}
EDIT:
See answer from nos regarding blocking/non-blocking configuration issues.
Your real problem is this line:
fcntl(pfd[0],F_SETFL,O_NDELAY);
This sets the read end pipe to non-blocking. So every read() call will return as much data as there is in the buffer, or return -1 and set errno to EWOULDBLOCK if there's no data to be read at this particular time.
However, your code does not handle that case, it only checks if(nread == 0) and prints out the buffer even if you didn't read anything. So remove that line.
If you do not want to send fixed size messages, or want to keep the read end non-blocking, things becomes more tricky, as you have to account for at least these cases:
read() returning -1 and sets errno to EWOULDBLOCK (just try read() again).
read() reads the first 4 bytes of your "message", and the next read returns the rest of the message.
read() reads the first message, and half of the subsequent message.
i.e. you need some form of framing/delimiters on your messages that you need to handle, unless you just need to stream the content of the pipe further on.
Read does not nul-terminate the input.
To print a character buffer that isn't nul-terminated, do like this:
printf("MSQ=%.*s\n", nread, buf);
If you want to nul-terminate the read buffer you need to make 2 changes.
1 . Increase the size of the buffer to MSGSIZE+1:
char buf[MSGSIZE + 1];
2 . nul-terminate buf after each read.
buf[nread > 0 ? nread : 0] = 0; // read returns -1 on error
Also
msg1 and msg2 are string literals which are smaller than MSGSIZE.
The thing about garbage is this principle called GIGO: garbage in, garbage out.
Don't want garbage in the pipe? Use a drain trap on your kitchen sink.