 |
 |
socket programming in C issue
|
 |
|
 |
|
Mac Enthusiast
Join Date: Sep 2000
Location: France
Status:
Offline
|
|
Hi everyone
I just happened to learn a few things about network programming in C, but I ran across some issues in my own programs I hope you can solve.
What I'm trying to do is pretty simple : I just want to program a client program connecting to a server program on a predefined port, and sending a multiline message all at once to a server when the user enters the line "." (like the mail tool I think)
So here's the server code :
Code:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#define MYPORT 3490
#define BACKLOG 10 /* Max queued connections */
#define MAX 1000 /* buffer max char */
main() {
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int listener_fd, new_fd;
int sin_size = sizeof(struct sockaddr_in);
char buf[MAX];
int yes = 1;
if ((listener_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(listener_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
bind(listener_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
listen(listener_fd, BACKLOG);
new_fd = accept(listener_fd, (struct sockaddr *)&their_addr, &sin_size);
recv(new_fd, buf, MAX, 0);
printf("Received from : %s\n%s\n",inet_ntoa(their_addr.sin_addr) ,buf);
close(listener_fd);
}
and now the client code :
Code:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#define PORT 3490
#define MAX 1000 /* mess max char */
#define MAXLINE 100
void getmess(char *mess); /* function that gets the user message */
main() {
struct sockaddr_in server_addr;
int sock_fd;
int sin_size = sizeof(struct sockaddr_in);
char mess[1000];
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&(server_addr.sin_zero), '\0', 8);
if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
i=getmess(mess); /* wait for full message, ending with "." */
if (send(sock_fd, mess, strlen(mess), 0) == -1) { /* send the message to the server */
perror("send");
exit(1);
}
close(sock_fd);
}
void getmess(char *mess) {
char *last_line;
int i=0;
int comp;
while( (last_line = fgets(mess+i,MAXLINE ,stdin)) != NULL && (comp = strcmp(last_line, ".\n")) != 0)
i = (strrchr(mess, '\n') - mess) + 1;
if (comp == 0)
*(mess+i)='\0'; /* erase the "." from the message to send */
}
Now the problem is that, when the server receives a multiline message and prints it, a lot of garbage characters are also printed at the end.
For example if I send the message :
Code:
hello
my name's axel
.
the server will print :
Code:
hello
my name's axel
ÿö?p
?Ì¿ÿö
However, the server receives one-line messages (the second line being "." ) perfectly.
Any idea as to what's going wrong ?
Thx in advance for your help 
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Aug 2002
Status:
Offline
|
|
Hi Axel,
What you're seeing is the "junk" characters of an uninitialized string buffer. When you allocate the "buf" string/array, the memory allocated to the buf variable contains 1000 (MAX) bytes of old junk - this memory area is not cleared for you. When you later make the call to recv, recv fills the first, say 100 bytes of this array with the actual characters, and the remaining 900 bytes contain the same old crud as before.
When you print buf, it prints all of the characters in it, both the data from recv, and all data beyond that up until it finds an "end of line" character. Since you haven't set an end of line character in buf (recv doesn't do that for you), it will either print all 1000 bytes of buf or less if one of the 900 (in my example) uninitialized bytes happen to contain an end of line character.
What you need to do is to find out how many bytes you got from your recv call, and then set an end of line character manually, like so:
int n = recv(new_fd, buf, MAX, 0);
buf[n] = '\0';
recv() returns the number of bytes read, so you know that the last "legitimate" character in buf resides at buf[n-1]. Setting the next character to the null character tells all of the string functions in C where the end of line is.
So, a long winded response but hopefully a clear one :-)
Cheers,
-Fredrik
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Enthusiast
Join Date: Sep 2000
Location: France
Status:
Offline
|
|
Originally posted by karamellkungen:
Hi Axel,
What you're seeing is the "junk" characters of an uninitialized string buffer. When you allocate the "buf" string/array, the memory allocated to the buf variable contains 1000 (MAX) bytes of old junk - this memory area is not cleared for you. When you later make the call to recv, recv fills the first, say 100 bytes of this array with the actual characters, and the remaining 900 bytes contain the same old crud as before.
When you print buf, it prints all of the characters in it, both the data from recv, and all data beyond that up until it finds an "end of line" character. Since you haven't set an end of line character in buf (recv doesn't do that for you), it will either print all 1000 bytes of buf or less if one of the 900 (in my example) uninitialized bytes happen to contain an end of line character.
What you need to do is to find out how many bytes you got from your recv call, and then set an end of line character manually, like so:
int n = recv(new_fd, buf, MAX, 0);
buf[n] = '\0';
recv() returns the number of bytes read, so you know that the last "legitimate" character in buf resides at buf[n-1]. Setting the next character to the null character tells all of the string functions in C where the end of line is.
So, a long winded response but hopefully a clear one :-)
Cheers,
-Fredrik
Very clear indeed
Thx a lot for your help ! 
|
|
|
| |
|
|
|
 |
 |
|
 |
|
|
|
|
|

|
|
 |
Forum Rules
|
 |
 |
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
 |
 |
 |
 |
|
 |
|