Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm really confused. I have a C server and it was working great, but then I added some code, and I thought it was working fine until my c program randomly started changing the value of an int to a negative value.
Basically I'm having my server output the total bytes sent and midway through the transmission, always around 2100000000 bytes, the total bytes becomes negative. Here's an example of my output file. The value can't just become negative if you look at my code. So I suspect it's something weirder.
"345000","1470253912","59203","5592","2069901108"
"348000","1470253912","475539","4194","2092449162"
"351000","1470253912","830291","2796","2112043464"
"354000","1470253913","243217","1398","2133985176"
"357000","1470253913","708686","13980","-2135434834"
"360000","1470253914","173646","9786","-2109094024"
"363000","1470253914","514938","6990","-2089413400"
Anyways the thing I added, I commented it out, and I still came across the same error. Just for reference it's commented out in my code under tags "NEW STUFF ADDED". (I added it because of this post: Terminating C program on command line, but make sure writer is finished writing
)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/time.h>
int PORT_NUM = 0;
int RecordRate = 3000;
FILE *fp;
typedef struct timeval timeval;
timeval time_;
void error(const char *msg)
{
perror(msg);
exit(1);
}
//NEW STUFF ADDED
//void sig_handler(int signo)
//{
// if (signo == SIGINT) {
// printf("received SIGINT\n");
// exit(0);
// fflush(fp);
// }
//}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1000000];
struct sockaddr_in serv_addr, cli_addr;
int n;
PORT_NUM = atoi(argv[1]);
fp = fopen(argv[2],"w");
// NEW STUFF ADDED
// if (signal(SIGINT, sig_handler) == SIG_ERR)
// printf("\ncan't catch SIGINT\n");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
//portno = atoi(argv[1]);
portno = PORT_NUM;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,10);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
int counter = 0;
int total_bytes_sent = 0;
while(1){
bzero(buffer,1000000);
n = read(newsockfd,buffer,999999);
if (n < 0) {
error("ERROR reading from socket");
}
else if (n != 0) {
total_bytes_sent += n;
gettimeofday(&time_, NULL);
if(counter%RecordRate==0){
printf("counter %d \n", counter);
printf("Bytes Sent %d \n", total_bytes_sent);
fprintf(fp,"\"%d\",\"%ld\",\"%d\",\"%d\",\"%d\"\n", counter, time_.tv_sec, time_.tv_usec, n,total_bytes_sent);
}
counter++;
}
}
fclose(fp);
close(newsockfd);
close(sockfd);
return 0;
}
I swear I'm not trolling. I feared it was what I added that did this, but once I commented it out I got the same error. The thing is the error only became present after I added the code. So causation, correlation, no link?
How can this happen? And why always around 2100000000 bytes.
It's not the end of the world. I mean I can just hardcode something that makes sure the value is always, positive but I'm curious as to how this happens. Thanks.
Simply because ordinary signed int variables overflow at 231-1 (2147483647) and become negative.
Since this order of magnitude is not enough to keep track of the values you need, you should be using a 64bit variable to that - declare your variable as long long - and take proper care of this change in the places you are outputting this value to a text stream, and you should be good.
Related
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
char *result1 = "Ian G. Harris";
char *result2 = "Joe Smith";
char *result3 = "Jane Smith";
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
error("ERROR on accept");
}
while (strcmp(buffer, "+++") != 0)
{
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Address server started\n");
if (strcmp(buffer, "harris#ics.uci.edu\n") == 0)
{
printf("%s\n", result1);
}
else if(strcmp(buffer, "joe#cnn.com\n") == 0)
{
printf("%s\n", result2);
}
else if(strcmp(buffer, "jane#slashdot.org\n")==0)
{
printf("%s\n", result3);
}
}
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3)
{
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
while (strcmp(buffer, "+++") != 0)
{
printf("> ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
}
return 0;
}
I am new to c and I am writing a server.c and client.c. The problem of my code is that I cannot make the program keep taking inputs until I enter "+++" to quit. The correct output is shown below:
client terminal:
> harris#ics.uci.edu
Ian G. Harris
> joe#cnn.com
Joe
>
server terminal:
Address server started
harris#ics.uci.edu
joe#cnn.com
in my code, when I enter "harris#ics.uci.edu" in client terminal, it does the following:
> harris#ics.uci.edu
(empty line)
and it does not take any input anymore.
Is there something wrong in the while loop? can someone help me to fix it? Thanks in advance.
Few things:
In the client loop, you do a write and a read on the socket. But your server never writes to that socket(no write call in the server, only read). As a result, your client gets blocked on the read call. That's why you cannot enter more...
In general, you need to check how much you wrote in and keep writing until done (a loop is needed).
int n = 0;
while (n != strlen(buffer){
n += write(sockfd,&buffer[n],strlen(buffer)-n);
}
Same goes for reading from a socket:
int n = 0;
while (n != strlen(buffer){
n += read(sockfd,&buffer[n],strlen(buffer)-n);
}
Here's what I believe is likely happening.
Client sends some chunk of data. Possibly all of the string harris#ics.uci.edu, but possibly less.
The server reads some chunk of this, most likely less than the full string, say harris#ic.
The server performs the strcmp, which doesn't match anything, so returns to the top of the loop.
The server reads the remainder of the email, say s.uci.edu into buffer, thus overwriting it.
Again, this doesn't match anything, so the server goes to the top of the while loop again.
The server hangs on the read call, waiting for data from the client. Because the client is waiting for a reply, it's stuck on its own read call. ...And nothing else happens.
There are two main problems here. First, TCP sockets are just streams of bytes, and when you read data from them, the OS no longer keeps it around. You are now expected to handle any previously- or partially-read data if you need. And second, the OS often transmits (both sending and receiving) fewer bytes than you request. While you ask that the full string harris#ics.uci.edu be sent, only a portion of that may be sent, or only a portion of that may be read on the other side.
This means two things for you. It's always important to check the amount of data read/written any time you call read(2) or write(2), but it's crucial in networking. Make sure you read/write as much as you need (the full email in this case) before moving on to, for example, waiting for a reply.
The second thing is that you need some way of delineating full messages and buffering partial messages. In what you've got, as is common in lots of text-based messaging protocols, the newline \n is your delimiter. So instead of a single call to read(2) in the server, you need something like this (pseduocode):
while newline not in data:
data += read(sockfd, ...)
Once you receive your newline, process the full message, but don't throw away any extra bytes you've read from the next message. Keep those around, and append the next bytes read from the socket to them, and so on.
EDIT:
Note that it's usually better to use recv(2) and send(2) when working with sockets. The read(2)/write(2) system calls will work just fine, but the others are more clear when working with sockets, and allow you to specify other flags, for example, peeking at the bytes currently on the socket or waiting until all the bytes you request are available before returning.
I am trying to write a server that can handle at most 5 concurrent clients.
Whenever a client gets successfully connected to the server & the number of clients is less than or equal to 5, the server sends a welcome message, generates a 5 digit unique random number for identifying that client, sends this number to the client and prints this number in the console.If the number of clients tends to be greater than 5, then for each new request, it just sends a message "Connection Limit Exceeded" to the client & closes the connection.
Client just prints the messages sent by the server.
The problem I'm facing is that, the random number is not being propagated properly to the client.Few times the client prints the same number as generated by the server but few times the client just prints 0(as the variable storing incoming value of that random number is initialized to 0).
What could be the reason behind this?
Here are the codes for client and server:
server:
/* A simple server in the internet domain using TCP
The port number is passed as an argument
This version runs forever, forking off a separate
process for each connection
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <stdlib.h>
void dostuff(int); /* function prototype */
void write_once (int sock);
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, pid, count = 0;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
count++;
if (pid < 0)
error("ERROR on fork");
if (pid == 0 && count <=5 ) {
close(sockfd);
dostuff(newsockfd);
exit(0);
}
if (pid == 0 && count >= 5 ) {
close(sockfd);
write_once(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
/******** DOSTUFF() *********************
There is a separate instance of this function
for each connection. It handles all communication
once a connnection has been established.
*****************************************/
void dostuff (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = write(sock,"Welcome\n",8);
if (n < 0) error("ERROR writing to socket");
srand((unsigned int)time(NULL));
int r = rand() % 90000 + 10000;
int converted_r = htonl(r);
n = write(sock, &converted_r, sizeof(converted_r));
if (n < 0) error("ERROR writing to socket");
printf("%d\n", r);
}
void write_once (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = write(sock,"Connection Limit Exceeded!!",28);
if (n < 0) error("ERROR writing to socket");
}
client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int received_int = 0;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
n = read(sockfd, &received_int, sizeof(received_int));
if (n < 0)
error("ERROR reading from socket");
printf("%d\n", ntohl(received_int));
close(sockfd);
return 0;
}
Reference
The issue is that TCP is a stream oriented protocol, and not packet oriented. So it may happen that
The first read() of the client reads what the first write() of the server sent ("Welcome")
The second read() of the client reads what the second write() of the server sent (Your number)
This is what you expect and what sometimes happens.
However, it might also be that the client reads the data of both writes of the server at once! This usually happens when
either the server aggregated the two writes to a single tcp-packet
or the client reads the data after both tcp segments with data arrived
You cannot make sure what happens and cannot rely on any specific behaviour.
How to fix this depends solely on your protocol. If the first message is always "Welcome\n", then try to read only 8 bytes first. If you happen to read n < 8 bytes, you have to retry and read 8-n bytes to get the rest of the message. Subsequently read sizeof(received_int) bytes, also watching for the real number of bytes received.
If the message is of variable length you will have to use some kind of framing like a preceding length-byte or something like that.
I have a C server that writes packet data to an output file. The problem is I terminate the server in terminal using control c, and I've noticed that my output file is never finished writing to. Is there a way to make sure that my output file is completely written to before quitting?
(I know I could just let the server run longer so I'm sure the data I want has been written, but I'm looking for an alternative method)
Thanks
Here's my code for reference.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/time.h>
int PORT_NUM = 0;
int RecordRate = 3000;
typedef struct timeval timeval;
timeval time_;
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1000000];
struct sockaddr_in serv_addr, cli_addr;
int n;
FILE *fp;
PORT_NUM = atoi(argv[1]);
fp = fopen(argv[2],"w");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
//portno = atoi(argv[1]);
portno = PORT_NUM;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,10);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
int counter = 0;
int total_bytes_sent = 0;
while(1){
bzero(buffer,1000000);
n = read(newsockfd,buffer,999999);
if (n < 0) {
error("ERROR reading from socket");
}
else if (n != 0) {
total_bytes_sent += n;
gettimeofday(&time_, NULL);
if(counter%RecordRate==0){
printf("counter %d \n", counter);
fprintf(fp,"\"%d\",\"%ld\",\"%d\",\"%d\",\"%d\"\n", counter, time_.tv_sec, time_.tv_usec, n,total_bytes_sent);
}
counter++;
//print format: packet number, time Sec, time milli Sec, bytes in packet, total bytes sent
// example: "11182","1465921447","196422","3100","26821100"
}
}
fclose(fp);
close(newsockfd);
close(sockfd);
return 0;
}
You could set a custom handler for SIGINT in which you set a flag, and then exit gracefully whenever that flag is set.
#include <stdlib.h>
#include <signal.h>
volatile sig_atomic_t flag = 0;
void handle_int(int sig)
{
flag = 1;
}
int main()
{
signal(SIGINT, handle_int); // intercept SIGINT
while (!flag)
{
// do work ...
}
// cleanup, fflush, etc...
return 0;
}
Note that calling fflush directly in the signal handler is unsafe.
The // do work part obviously should be relatively short, so that the flag is checked regularly throughout the lifetime of the application.
In Linux you can use the EVIOCGKEY ioctl to check if a key is pressed and then break out of the while (1) loop.
#include <fcntl.h>
#include <linux/input.h>
#include <sys/ioctl.h>
int rdKey(int fd, int key) {//faster not to open file every time the function is called
// const char *keyboard = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
// int fd = open(keyboard, O_RDONLY);
char arr[(KEY_MAX+7)/8];
memset(arr, 0, sizeof(arr));
ioctl(fd, EVIOCGKEY(sizeof(arr)), arr);
return !!(arr[key/8] & (1<<(key % 8)));
}
You would pass a file descriptor for an input device like a keyboard and then either the key number or a macro from input.h like KEY_A for 'a' and it would return 1 if the key is pressed and 0 if not.
Another approach to consider would be have the application fork() with the child process becoming the server and the parent remain attached to the terminal waiting for input with the two communicating through a socket or pipe.
Before doing the fork() the parent would create a socket or pipe which it will use to communicate with the child process. The user could then type commands into the parent process still attached to the terminal and the parent process would then echo commands to the child process through the socket or pipe.
The child would use select() and include the communication socket/pipe in the list of descriptors. So where as your code above uses only a single socket with the read() you would instead use a select() with both the socket shared by with the parent as well as the socket from the accept with a check to determine if there is a command from the parent waiting to be read or more server work to do. The child can then do any tidying up needed and exit cleanly with the parent doing a wait() for it to finish up and then the parent exits itself.
Sorry I don't have any code example handy. See the following stackoverflow for details about sockets and select().
Is it possible (and safe) to make an accepting socket non-blocking?
c++ select async programming
Asynchronous C client for a multiclient C server
How do I change a TCP socket to be non-blocking?
working of fork in c language
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am writing a client / server system in which the client sends a record from client to server. I am trying to represent the data as a struct, but I do not successfully recv() the struct at the server end.
Here is my code:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#pragma pack(1)
struct emp
{
int id;
char *name;
} emp1, emp3;
#pragma pack(0)
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
memset(recvBuff, '0', sizeof(recvBuff));
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
serv_addr.sin_addr = inet_addr("192.168.0.105");
if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
emp1 = (struct emp *) malloc(sizeof(struct emp));
emp1.name = (char *) malloc((size)*(sizeof(char)));
printf("Enter name of employee : ");
scanf(" %[^\n]s", emp1.name);
printf("Enter emp id : ");
scanf(" %d", &emp1.id);
unsigned char *data = (unsigned char*) malloc(sizeof(regn));
memcpy(data, ®n, sizeof(regn));
sendto(sockfd, data, sizeof(emp1), 0, (SOCKADDR *) &serv_addr,
sizeof(serv_addr));
close(sockfd);
}
and my server is like this
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
struct emp
{
int id;
char *name;
} emp1, emp3;
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
FILE *fp, *fp1;
char recvBuf[1025];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
if(recvfrom(sd, recvBuf, recvBufSize, 0,
(struct sockaddr *) &clientAddr, &len) < 0)
{
printf("Error receiving message from client\n");
}
else
{
printf("Message received:%s\n", recvBuf);
printf("Size :%d\n", strlen(recvBuf));
memcpy(&emp1, recvBuf, sizeof(emp));
printf("name:%s\n", emp1.name );
printf("is:%d\n", emp1.id);
}
you are sending a struct which contains an integer and a char pointer. This pointer points to a completly random location, on the receiving system.
You have to send the content name points to.
You could send every member of the struct on its own. For members with variable length, you have to send the size first and allocate it on the receiving end.
As stated by John Bollinger: One of your structs is packed, the other not. this may cause additional problems with layout and size of the struct and is probably unnecessary .
Added this answer to answer to specific questions of the OP (it may seem a bit off track of the original question).
An example of simple streaming. It is simple because in a real streaming scenario you need object id's to be able to instantiate and load the real classes. But if you know already what class you are sending or receiving, their is no need for this complexity. If you are sending multiple instances of classes then you need a more complex streaming mechanism. As microsoft did for instance in MFC, Borland in OWL, .NET also has mechanisms in place, ...
namespace OMCIPoco{
typedef std::vector<unsigned char> ucharvector;
SystemData::stream& operator <<(SystemData::stream& stream,const ucharvector& data);
SystemData::stream& operator >>(SystemData::stream& stream,ucharvector& data);
}
The cpp file :
SystemData::stream& operator <<(SystemData::stream& stream,const ucharvector& data)
{
stream << (unsigned long)data.size();
for (ucharvector::const_iterator it=data.begin();it<data.end();++it)
stream << *it;
return stream;
}
SystemData::stream& operator >>(SystemData::stream& stream,ucharvector& data)
{
unsigned long count;
stream >> count;
data.reserve(count);
for (unsigned int i=0;i<count;++i){
unsigned char c;
stream >> c;
data.push_back(c);
}
return stream;
}
Notice how the << and >> are in balance.
The stream is an interface that makes abstraction of the medium you are streaming to, it can be memory or disk or a networkstream. I can solve little endian problems using the streaming concept here as well, because the stream knows how to (de)serialise shorts, longs, ..., and it knows howto buffer as well.
You can use a flat structure as well avoiding the above complexity completely
class data{
public:
char name[20];
};
now using sizeof(data) will be correct because you will send the entire data struct. I used class here but struct works just the same way. The downside is that if the name contains only 10 charakters you will still send 20.
Sorry for a very generic sounding question.
let's say
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SERVER_ADDRESS "123.456.789.012"
#define CLIENT_ADDRESS "123.456.789.013"
#define SERVER_TCP_PORT "1234"
#define CLIENT_TCP_PORT "1235"
int main()
{
printf("o halo thar");
int sockfd, new_sockfd, msg_len;
void * got_msg = "got ur msg!";
void * message;
struct sockaddr_in server_address, client_address;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("socket is opened");
bzero((char * ) &server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(SERVER_ADDRESS);
server_address.sin_port = htons(SERVER_TCP_PORT);
if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("socket is bound");
listen(sockfd,11);
printf("listening");
if (accept(sockfd, (struct sockaddr *) &client_address, sizeof(client_address)) < 0) // THE BAD LINE
exit(1);
printf("accepted");
int i;
for( i = 0; i < 11; i++)
{
msg_len = recv(sockfd, (void *) message, 10000, 0);
if (msg_len < 1)
exit(1);
printf("receiving msg");
if (send(sockfd, (void *) got_msg, 10000, 0) < 0);
exit(1);
printf("sending msg");
}
close(sockfd);
}
it should print abc if everything runs correctly. of course, my code doesn't. but i have localized the problem to this certain line of code which i'm calling somecode(). when i comment out somecode(), the program prints out ab (not c). however when not commented out, it prints nothing. so what kind of problem am i running into that affects previous statements? sorry for the vagueness. i'm just wondering how seeing somecode() is compiled fine, but when running, it influences executions of code that should be done before it reaches somecode()? Thanks guys.
EDIT:somecode() being
if (accept(sockfd, (struct sockaddr *) &client_address, sizeof(client_address)) < 0)
exit(1);
EDIT2:
sorry for being too vague. i even forgot to describe what happens to the program. it doesn't print anything out and i have to ctrl+c in order to get out of it.
Without seeing more code, anything that causes the program to exit unexpectedly (rather, be killed by the operating system) such as a segmentation fault or entering some form of code structure that does not allow it to return to your flow of execution, necessitating a kill via ctrl+c. Otherwise, the program should carry on without any issue.
What happens if you fflush(STDOUT) after each call to printf? Maybe your program is dying before printing all buffered output.