Related
I wrote a program in which I used to scan a string and a keyword from the user and return the number of occurrences of that keyword in the string. I used strcmp function after splitting the input string on white spaces and it worked fine.
Now, I am trying to do the same work using IPC with sockets where the client inputs the strings and keywords, and the server does the counting work. But in this case, I am not getting the same results for the same input. I looked at the return values of strcmp and found that it is returning non-zero values even when the input strings appear same to me.
What could be the cause & how can I resolve it?
Here is the code for server.
Reference: http://www.linuxhowtos.org/C_C++/socket.htm
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
//
char * input;
char * str;
char * word;
int i, wordLen, strLen;
char terminator = ';';
char * pch;
char * new;
int temp, count = 0;
//
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[36];
struct sockaddr_in serv_addr, cli_addr;
int n;
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");
bzero(buffer,36);
n = read(newsockfd,buffer,35);
if (n < 0) error("ERROR reading from socket");
//
input = (char *) malloc(36);
strcpy(input, buffer);
word = strchr(input, terminator);
temp = (strlen(input) - strlen(word));
str = (char *) malloc(temp);
//strlcpy(str, input, temp);
*str = '\0';
strncat(str, input, temp);
word++;
wordLen = strlen(word);
new = (char *) malloc(temp);
//strlcpy(str, input, temp);
strcpy(new, str);
strLen = strlen(str);
// if (word != NULL && str != NULL) printf("%s%d\n%s%d\n", word, wordLen, new, strLen);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
if(strcmp(pch, word) == 0) count++;
else printf("%s%s%d\n", pch, word, strcmp(pch, word));
pch = strtok (NULL, " ,.-");
printf("(%s)\n",word );
}
//
printf("Here is the output: %d\n",count);
//n = write(newsockfd,"Result: %d\n",count, 18);
if (n < 0) error("ERROR writing to socket");
free(str);
free(input);
free(new);
close(newsockfd);
close(sockfd);
return 0;
}
The only thing weird here is that you are assuming that every read() results in an null-terminated buffer. It returns a read count. Use it.
I'm wondering how to convert a char[] array to a char *
For example, in my code I am trying to access a web server using a hostname like "example.com"
Using my code, if I set a char * to "example.com" like below, it works perfectly.
char *host = "example.com";
But, what I really want to do is be able to read from a client program using a socket, write to a char[] array, and use the data obtained from that as the hostname.
For example,
char buffer[4096], hostname[4096];
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
wbhost = gethostbyname(hostname);
when my code gets to the last line, it just sits there, so I'm thinking its a typing problem, since when I do this:
char *host = "example.com";
...
wbhost = gethostbyname(host);
It works, and is able to get the data from the web and send it properly to my client program.
Any ideas are appreciated.
In the client program I use fgets() to read into a char[] from stdin then use write() to write to the socket for the server program to read. I had tried to use strcat() to add '\0' to the end of the char[] before writing to the socket but that didn't seem to do anything
Full Code: (Please ignore the comments, just trying different things for now)
client
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int sockfd, portnum, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[4096];
if(argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
portnum = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("ERROR opening Socket");
exit(1);
}
server = gethostbyname(argv[1]);
if(sockfd == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(1);
}
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(portnum);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR, on connecting");
exit(1);
}
printf("Please enter the Host name: ");
bzero(buffer, 4096);
fgets(buffer, 4095, stdin);
//strcat(buffer, "\0");
n = write(sockfd, buffer, strlen(buffer));
if(n < 0)
{
printf("Error writing to socket");
exit(1);
}
bzero(buffer, 4096);
n = read(sockfd,buffer, 4095);
if(n < 0)
{
printf("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
server
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portnum, clilen;
char buffer[4096], hostname[4096];
pid_t p_id;
struct sockaddr_in serv_addr, cli_addr;
int n, pid, hostname_len;
//char *host;
char *host = "example.com";
if(argc < 2)
{
fprintf(stderr, "ERROR, NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);//socket is made
if(sockfd < 0)
{
fprintf(stderr, "ERROR opening socket!!");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portnum = atoi(argv[1]);//port num
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnum);
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR on binding");
exit(1);
}
if( listen(sockfd, 5) < 0)
{
printf("ERROR ON LISTEN");
exit(1);
}
// accept
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if(newsockfd < 0)
{
fprintf(stderr, "ERROR on accept\n");
exit(1);
}
pid = fork();
if(pid == 0)
{
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
if(n < 0)
{//message from client
fprintf(stderr, "ERROR Reading from socket\n");
exit(1);
}
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
//variables used for acsessing webserver?
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
if(sockwb < 0)
{
printf("Error opeing websocket\n");
exit(1);
}
// hostname_len = sizeof(hostname) / sizeof(hostname[0]);
// printf("%d\n", hostname_len);
// memcpy(host, hostname, hostname_len);
// host[hostname_len] = '\0';
printf("%s\n", host);
// hostname[hostname_len] = '\0';
// host = &hostname[0];
//wbhost = gethostbyname(hostname);
wbhost = gethostbyname(host);
//printf("%s", wbhost->h_name);
printf("here2\n");
/*if(wbhost == NULL)
{
printf("NO SUCH web HOST\n");
exit(1);
}
*/
bzero((char*) &webser_addr, sizeof(webser_addr));
webser_addr.sin_family = AF_INET;
bcopy((char *)wbhost->h_addr, (char *)&webser_addr.sin_addr.s_addr, wbhost->h_length);
webser_addr.sin_port = htons(wbport);
// printf("here3\n");
if(connect(sockwb, (struct sockaddr *) &webser_addr,sizeof(webser_addr)) < 0)
{
printf("Error on web connecting\n");
exit(1);
}
bzero(webbuf, 4096);
strcpy(webbuf, "GET / HTTP/1.0\r\nHost: ");
// strcat(webbuf, hostname);
strcat(webbuf, host);
strcat(webbuf, "\r\nConnection: close\r\n\r\n");
// const char * request = "GET / HTTP/1.0\r\nHost: example.com\r\nConnection: close\r\n\r\n";
// printf("%s\n", request);
// x = write(sockwb, request, strlen(request));
printf("%s\n", webbuf);
x = write(sockwb, webbuf, strlen(webbuf));
if(x < 0)
{
printf("Error writing to web sock");
exit(1);
}
bzero(webbuf, 4096);
x = read(sockwb, webbuf, 4096);
if(n < 0)
{
printf("Error reading from web socket");
exit(1);
}
printf("%d\n", (int)strlen(webbuf));
printf("%s\n",webbuf);
n = write(newsockfd, webbuf, 4095 );//write back to client
if(n < 0)
{
fprintf(stderr, "ERROR WRITING to socket");
exit(1);
}
//printf("%s\n", webbuf);
}//end of if pid==0
printf("closing client");
close(newsockfd);//closing client socket
}while(1);
return 0;
}
The code you posted runs unimpeded. When you ask for help, you should always post a complete, verifiable example. Check that the code you post actually reproduces the problem!
Looking at what the code does, it seems that in the server, you meant to use the host name that you read as the argument to gethostbyname. You can do that with
host = &hostname[0];
or simpler
host = hostname;
or by not using two separate variables in the first place.
When you use an array in a context that expects a value (as opposed to e.g. taking its address or its sizeof), the array decays into a pointer to its first element. So here hostname is equivalent to hostname[0].
After that change, check the trace closely, or, to make the problem more visible, change the tracing line to
printf("[%s]\n", hostname);
You'll see
[aaa.com
]
The client reads a line with fgets, which includes the terminating newline character in its count. The client dutifully forwards the complete line to the server. And so the server looks up a host name containing a newline character, which doesn't exist. You don't check the return code of gethostbyname (you should!), it returns a null pointer, and the program crashes when it tries to read from it.
#Gilles is right, you have an '\n' at the end of the hostname, the following piece of code replaces the '\n' by 0 which is the equivalent of the character '\0':
extern int h_errno;
...
hostname[strlen(hostname) - 1] = 0;
wbhost = gethostbyname(hostname);
if (!wbhost) {
printf("Failed! %s\n", strerror(h_errno));
exit(1);
}
...
A char[] is an array of chars. A char* is a pointer to a char - generally (but not always) the start of a string.
If you want to get a pointer to the start of your array, you don't even need to do anything! This conversion happens implicitly:
char hello[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
// or: char hello[] = "hello"; (equivalent to above)
printf("%s", hello); // prints hello
puts(hello); // also prints hello
char *hello2 = hello;
puts(hello2); // also prints hello
Probably the easiest way to 'convert' char[] to char * is:
char example_array[] = "example";
char * example_pointer = (char *)calloc(1, strlen(example_array) + 1); // + 1 for the '\0' character
strcpy(example_pointer, example_array);
I am trying to send variable length message in TCP but the message length that
is printed is always 0. I am using beej guide code for send and receive and pack and unpack to send the header length.Can someone please point out the mistake.
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_SIZE 50
void error(const char *msg)
{
perror(msg);
exit(1);
}
void packi32(unsigned char *buf, unsigned long i)//from beej guide
{
*buf++ = i>>24; *buf++ = i>>16;
*buf++ = i>>8; *buf++ = i;
}
/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
int total=0;
int bytesleft=*len;
int n=0;
/* send all the data */
while(total<*len){
/* send some data */
n=send(s,buf+total,bytesleft,0);
/* break on error */
if(n==-1)
break;
/* apply bytes we sent */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually send here */
*len=total;
/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}
int sendus(int s,char *msg)
{
char buf[4];//here 4 is header length
int len = strlen(msg);
packi32(buf,len);
int ll = 4;// ll is header length containing message length
int x;
if((x = sendall(s,buf,&ll))< 0)
printf("value of sent x %d\n",x);
int y = sendall(s,msg,&len);
return y;
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
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");
char msg[1024] = "hello";
int xx = sendus(sockfd,(char*)msg);
close(newsockfd);
close(sockfd);
return 0;
}
client code
#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>
#include<errno.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
/** unpacki32() -- unpack a 32-bit int from a char buffer (like ntohl())
*/
unsigned long unpacki32(unsigned char *buf)
{
return (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
}
/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout){
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;
/* clear the receive buffer */
bzero(buf,*len);
time(&start_time);
/* receive all data */
while(total<*len){
/* receive some data */
n=recv(s,buf+total,bytesleft,0);
/* no data has arrived yet (non-blocking socket) */
if(n==-1 && errno==EAGAIN){
time(¤t_time);
if(current_time-start_time>timeout)
break;
sleep(1);
continue;
}
/* receive error or client disconnect */
else if(n<=0)
break;
/* apply bytes we received */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually received here */
*len=total;
/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
}
int recvme(int s, char *buf)
{
char len[4];
int l = 4;
int n = recvall(s,len,&l,10);
int msg_len = unpacki32(len);
printf("msg_length :%d",msg_len);
int z ;
z = recvall(s,buf,&msg_len,10);
return z;
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[1024];
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");
n = recvme(sockfd, buffer);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
The basic cause for the failure is in the server's line
int xx = sendus(sockfd,(char*)msg);
- sockfd is the listen() socket, but we have to use the newsockfd returned from accept(), i. e.
sendus(newsockfd, msg);
I am pasting my client and server code below. My program is running fine, except that i am trying to send an ipaddress in my src and dest field, and for some reason, even though i am sending it as 131.199.166.232, it is printing as 232.166.199.131. But rest of my packet values are printed in a proper way. I have used memcpy(), so I feel its a memcpy thing, which somewhere I did wrong, but in Beej's guide as there is a section # the byte ordering in different computer architectures.....I have not used htonl() and all, so maybe it is because of that.Please guide me as where I am going wrong. Also kindly tell me the way i am sending data, how should the htonl() function can be used in my code....Thanks in advance.
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAXPROFILES 2
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
unsigned char buf[1024];
unsigned int srcAddress = 2193598184;
unsigned int destAddress = 2193598182;
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
header outObj;
int j =0;
int i =0;
// for loop for doing the malloc so that we can allocate memory to all profiles
for(i=0;i<MAXPROFILES;i++){
outObj.profiles[i].data = malloc(5);
}
for(i=3;i>=0;i--){
outObj.src[i] = (srcAddress >> (i*8)) & 0xFF;
outObj.dst[i] = (destAddress >> (i*8)) & 0xFF;
printf("%d",outObj.src[i]);
}
outObj.ver = 1;
outObj.n = 2;
memcpy(buf,&outObj.src,4);
memcpy(buf+4,&outObj.dst,4);
memcpy(buf+8,&outObj.ver,1);
memcpy(buf+9,&outObj.n,1);
outObj.profiles[0].length = 5;
outObj.profiles[0].type = 1;
outObj.profiles[1].length = 5;
outObj.profiles[1].type = 2;
for(i=0;i<MAXPROFILES;i++){
for(j=0;j<5;j++){
outObj.profiles[i].data[j] = j+1;
}
}
int k = 10;
// for loop to do memcopy of length,type and data.
for(i=0;i<MAXPROFILES;i++){
memcpy(buf+k,&outObj.profiles[0].length,1);
memcpy(buf+k+1,&outObj.profiles[0].type,1);
memcpy(buf+k+2,outObj.profiles[0].data,5);
k +=7;
}
if (argc < 3) {
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]); //Convert ASCII to integer
sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address
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);
printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR in connection");
printf("SUCCESS !!! Connection established \n");
if (write(sockfd, buf, k) < 0)
{
error("Write error has occured ");
}
return 0;
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXPROFILES 2
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
unsigned char buf[1024];
int my_data2[10] = {1,3,9,10};
int my_data[10] = {1,2,3,4,5};
int myDataBinary[500] = {0};
int myDataBinary2[500] = {0};
int recData[500] = {0};
int index1=0;
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
header outObj;
int j =0;
int i =0;
if (argc < 2) {
fprintf(stderr,"usage: %s port_number1",argv[0]);
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in 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 = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR DETECTED !!! There was a problem in binding");
listen(sockfd, 10);
clilen = sizeof(cli_addr);
printf("Server listening on port number %d...\n", serv_addr.sin_port);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR DETECTED !!! the connection request was not accepted");
int rc = read(newsockfd,buf,100);
if(rc < 0){
printf("error");
}
else {
printf("success %d",rc);
}
memcpy(&outObj.src,buf+0,4);
memcpy(&outObj.dst,buf+4,4);
memcpy(&outObj.ver,buf+8,1);
memcpy(&outObj.n,buf+9,1);
printf("\nsrc ip = ");
for(int i=0;i<4;i++){
printf("%d ",outObj.src[i]);
}
printf("\ndest ip = ");
for(int i=0;i<4;i++){
printf("%d ",outObj.src[i]);
}
printf("\nversion = %d",outObj.ver);
printf("\nnumber = %d",outObj.n);
int k = 10;
for(i=0;i<outObj.n;i++){
memcpy(&outObj.profiles[i].length,buf+k,1);
memcpy(&outObj.profiles[i].type,buf+k+1,1);
outObj.profiles[i].data = malloc(outObj.profiles[i].length);
memcpy(outObj.profiles[i].data,buf+k+2,5);
k +=7;
}
for(int i=0;i<outObj.n;i++){
printf("\nMessage %d :",i+1);
printf("\nLength : %d",outObj.profiles[i].length);
printf("\nType : %d",outObj.profiles[i].type);
for(int j=0;j<5;j++){
printf("\ndata %d : %d",j,outObj.profiles[i].data[j]);
}
}
for(int i=0; i<sizeof(my_data)/sizeof(int);i++)
{
if(my_data[i] > 0){
index1 = my_data[i];
myDataBinary[index1] = 1;
printf("my data %d = %d\n",index1,myDataBinary[index1]);
}
}
for(int i=0; i<sizeof(my_data2)/sizeof(int);i++)
{
if(my_data2[i] > 0){
index1 = my_data2[i];
myDataBinary2[index1] = 1;
printf("my data %d = %d\n",index1,myDataBinary2[index1]);
}
}
int sumRecievedData = 0;
int sumMyData = 0;
int sumMultpliedData = 0;
float Cov =0;
float sdMyData = 0;
float sdRecievedData =0;
int n = 500;
float rho;
for(int i=0;i<outObj.n;i++){
index1=0;
for (int j=0; j<outObj.profiles[i].length;j++) {
if(outObj.profiles[i].data[j] > 0){
index1 = outObj.profiles[i].data[j];
recData[index1] = 1;
printf("rec data %d = %d\n",index1,recData[index1]);
}
}
}
return 0;
}
an ip address is really just an array of unsigned char.
uchar ip[] = {127,0,0,1};
Is a fine representation for a loopback address. But an array of four bytes, and a int really aren't that large; with one exception endiannes! So suppose I create the int which represents that ip. A naive approach might be:
int ip = (127<<24)|(0<<16)|(0<<8)|(1)
Of course, on little endian machines, like the x86 and arm it doing this:
char *char_ip = (void*)&ip;
and iterating over that aray would yield:
1, 0, 0, 127
But on a big endian machine, like a PowerPC, or a SPARC, we would have what we expect,
127, 0, 0, 1
Big endian is also known as "network byte order" which is what the n in htonl stands for: "host to network long". These functions are frequently used when reading or writing integers over the network. Suppose a server wants to send a client some number:
uint32_t important = htonl(42);
write(client, &important, sizeof important);
Then, to read it, the client goes:
uint32_t important;
read(server, &important, sizeof important);
important = ntohl(important);
The reason your ip address were flipped was because ip addresses are expected to be in network byte order, but yours were little endian instead. htonl on an int-type ip will flip it for you.
This is way too much code for me to read, but if you just want to create a byte array for serializing, you don't need any special functions at all, you can just write it algebraically:
unsigned char buf[sizeof(uint_type)];
uint_type value;
for (size_t i = 0; i != sizeof(uint_type); ++i)
{
// Little-endian
buf[i] = value >> (i * CHAR_BIT);
// Big-endian
buf[sizeof(uint_type - i - 1)] = value >> (i * CHAR_BIT);
}
Note that this code is independent of your system's endianness.
Since you asked, the htonl/ntohl functions are for dealing with uint32_t integers directly, without explicit char arrays:
uint32_t value;
myfile.read((char*)&value, sizeof(value)); // network endianness
value = ntohl(value); // host endianness
/* fiddle fiddle */
value = htonl(value);
yourfile.write((const char*)&value, sizeof(value));
(More typically you'd be writing to a socket rather than a file, I suppose.)
I am pasting my client and server code below. My program is running fine, except that i am trying to send an ipaddress in my src and dest field, and for some reason, even though i am sending it as 131.199.166.232, it is printing as 232.166.199.131. But rest of my packet values are printed in a proper way. I have used memcpy(), so I feel its a memcpy thing, which somewhere I did wrong, but in Beej's guide as there is a section # the byte ordering in different computer architectures.....I have not used htonl() and all, so maybe it is because of that.Please guide me as where I am going wrong. Also kindly tell me the way i am sending data, how should the htonl() function can be used in my code....Thanks in advance.
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAXPROFILES 2
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
unsigned char buf[1024];
unsigned int srcAddress = 2193598184;
unsigned int destAddress = 2193598182;
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
header outObj;
int j =0;
int i =0;
// for loop for doing the malloc so that we can allocate memory to all profiles
for(i=0;i<MAXPROFILES;i++){
outObj.profiles[i].data = malloc(5);
}
for(i=3;i>=0;i--){
outObj.src[i] = (srcAddress >> (i*8)) & 0xFF;
outObj.dst[i] = (destAddress >> (i*8)) & 0xFF;
printf("%d",outObj.src[i]);
}
outObj.ver = 1;
outObj.n = 2;
memcpy(buf,&outObj.src,4);
memcpy(buf+4,&outObj.dst,4);
memcpy(buf+8,&outObj.ver,1);
memcpy(buf+9,&outObj.n,1);
outObj.profiles[0].length = 5;
outObj.profiles[0].type = 1;
outObj.profiles[1].length = 5;
outObj.profiles[1].type = 2;
for(i=0;i<MAXPROFILES;i++){
for(j=0;j<5;j++){
outObj.profiles[i].data[j] = j+1;
}
}
int k = 10;
// for loop to do memcopy of length,type and data.
for(i=0;i<MAXPROFILES;i++){
memcpy(buf+k,&outObj.profiles[0].length,1);
memcpy(buf+k+1,&outObj.profiles[0].type,1);
memcpy(buf+k+2,outObj.profiles[0].data,5);
k +=7;
}
if (argc < 3) {
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]); //Convert ASCII to integer
sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address
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);
printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR in connection");
printf("SUCCESS !!! Connection established \n");
if (write(sockfd, buf, k) < 0)
{
error("Write error has occured ");
}
return 0;
}
Server Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXPROFILES 2
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
unsigned char buf[1024];
int my_data2[10] = {1,3,9,10};
int my_data[10] = {1,2,3,4,5};
int myDataBinary[500] = {0};
int myDataBinary2[500] = {0};
int recData[500] = {0};
int index1=0;
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
header outObj;
int j =0;
int i =0;
if (argc < 2) {
fprintf(stderr,"usage: %s port_number1",argv[0]);
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in 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 = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR DETECTED !!! There was a problem in binding");
listen(sockfd, 10);
clilen = sizeof(cli_addr);
printf("Server listening on port number %d...\n", serv_addr.sin_port);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR DETECTED !!! the connection request was not accepted");
int rc = read(newsockfd,buf,100);
if(rc < 0){
printf("error");
}
else {
printf("success %d",rc);
}
memcpy(&outObj.src,buf+0,4);
memcpy(&outObj.dst,buf+4,4);
memcpy(&outObj.ver,buf+8,1);
memcpy(&outObj.n,buf+9,1);
printf("\nsrc ip = ");
for(int i=0;i<4;i++){
printf("%d ",outObj.src[i]);
}
printf("\ndest ip = ");
for(int i=0;i<4;i++){
printf("%d ",outObj.src[i]);
}
printf("\nversion = %d",outObj.ver);
printf("\nnumber = %d",outObj.n);
int k = 10;
for(i=0;i<outObj.n;i++){
memcpy(&outObj.profiles[i].length,buf+k,1);
memcpy(&outObj.profiles[i].type,buf+k+1,1);
outObj.profiles[i].data = malloc(outObj.profiles[i].length);
memcpy(outObj.profiles[i].data,buf+k+2,5);
k +=7;
}
for(int i=0;i<outObj.n;i++){
printf("\nMessage %d :",i+1);
printf("\nLength : %d",outObj.profiles[i].length);
printf("\nType : %d",outObj.profiles[i].type);
for(int j=0;j<5;j++){
printf("\ndata %d : %d",j,outObj.profiles[i].data[j]);
}
}
for(int i=0; i<sizeof(my_data)/sizeof(int);i++)
{
if(my_data[i] > 0){
index1 = my_data[i];
myDataBinary[index1] = 1;
printf("my data %d = %d\n",index1,myDataBinary[index1]);
}
}
for(int i=0; i<sizeof(my_data2)/sizeof(int);i++)
{
if(my_data2[i] > 0){
index1 = my_data2[i];
myDataBinary2[index1] = 1;
printf("my data %d = %d\n",index1,myDataBinary2[index1]);
}
}
int sumRecievedData = 0;
int sumMyData = 0;
int sumMultpliedData = 0;
float Cov =0;
float sdMyData = 0;
float sdRecievedData =0;
int n = 500;
float rho;
for(int i=0;i<outObj.n;i++){
index1=0;
for (int j=0; j<outObj.profiles[i].length;j++) {
if(outObj.profiles[i].data[j] > 0){
index1 = outObj.profiles[i].data[j];
recData[index1] = 1;
printf("rec data %d = %d\n",index1,recData[index1]);
}
}
}
for(int i=0;i<500;i++){
sumRecievedData += recData[i];
sumMyData += myDataBinary[i];
sumMultpliedData += recData[i] * myDataBinary[i];
}
printf("recSum = %d, mySum = %d, multSum = %d",sumRecievedData,sumMyData,sumMultpliedData);
Cov = (1.0/(n-1))*(sumMultpliedData - (1.0/n)*sumMyData*sumRecievedData);
sdMyData = sqrt((1.0/(n-1))*(sumMyData - (1.0/n)*sumMyData*sumMyData));
sdRecievedData = sqrt((1.0/(n-1))*(sumRecievedData - (1.0/n)*sumRecievedData*sumRecievedData));
printf("Covariance = %f, Variance 1 = %f, Variance 2 = %f",Cov,sdMyData,sdRecievedData);
if (sdMyData == 0.0 || sdRecievedData == 0.0){
rho = 0.0;
}else{
rho = Cov/(sdMyData*sdRecievedData);
}
printf("Pearson Coefficient = %f",rho);
return 0;
}
You need to decide how you want to send the data and convert data in that format right before:
if (write(sockfd, buf, k) < 0)
You use either of following:
htons() host to network short
htonl() host to network long
ntohs() network to host short
ntohl() network to host long
In general, you should use regular integers instead of byte arrays in your structs, then use hton...() to put those values be in network byte order when placing them into send buffers, and then use ntoh...() to put the values back into host byte order when copying them out of receive buffers. Your code operates in host byte order. Network transmissions should use network byte order.
With that said, IPv4 addresses are a special case, because there are extra functions available() for working with IP strings, which expect the numeric values to be in network byte order only.
Try something like this:
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAXPROFILES 2
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
struct profile_datagram_t
{
unsigned long src;
unsigned long dst;
unsigned char ver;
unsigned char n;
profile_t profiles[MAXPROFILES];
};
int main(int argc, char *argv[])
{
if (argc < 3)
{
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(0);
}
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
unsigned char buf[1024];
profile_datagram_t outObj;
int i;
int j;
outObj.src = inet_addr("130.191.166.232");
outObj.dst = inet_addr("130.191.166.230");
outObj.ver = 1;
outObj.n = 2;
memcpy(&buf[0], &outObj.src, 4);
memcpy(&buf[4], &outObj.dst, 4);
memcpy(&buf[8], &outObj.ver, 1);
memcpy(&buf[9], &outObj.n, 1);
int k = 10;
for(i = 0; i < MAXPROFILES; ++i)
{
outObj.profiles[i].length = 5;
outObj.profiles[i].type = i+1;
outObj.profiles[i].data = malloc(5);
for(j = 0; j < 5; ++j)
{
outObj.profiles[i].data[j] = j+1;
}
memcpy(&buf[k], &outObj.profiles[i].length, 1);
memcpy(&buf[k+1], &outObj.profiles[i].type, 1);
memcpy(&buf[k+2], outObj.profiles[i].data, 5);
k +=7;
}
sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (sockfd < 0)
error("ERROR in opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL)
{
closesocket(sockfd);
fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
portno = atoi(argv[2]); //Convert ASCII to integer
serv_addr.sin_port = htons(portno);
printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
{
closesocket(sockfd);
error("ERROR in connect");
}
printf("SUCCESS !!! Connection established \n");
i = 0;
while (i < k)
{
int rc = write(sockfd, &buf[i], k-i);
if (rc < 0)
{
closesocket(sockfd);
error("ERROR in write");
}
i += rc;
}
closesocket(sockfd);
return 0;
}
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXPROFILES 2
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
struct profile_datagram_t
{
unsigned long src;
unsigned long dst;
unsigned char ver;
unsigned char n;
profile_t profiles[MAXPROFILES];
};
int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "usage: %s port_number1", argv[0]);
exit(1);
}
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
struct in_addr addr;
unsigned char buf[1024];
int buflen;
profile_datagram_t outObj;
int i;
int j;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR in 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 in binding");
if (listen(sockfd, 10)) < 0)
error("ERROR in listening");
printf("Server listening on port number %d...\n", portno);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
closesocket(sockfd);
if (newsockfd < 0)
error("a connection request was not accepted");
buflen = 0;
while (buflen < 10)
{
int rc = read(newsockfd, &buf[buflen], 10-buflen);
if(rc <= 0)
{
closesocket(newsockfd);
error("ERROR in read");
}
buflen += rc;
}
memcpy(&outObj.src, &buf[0], 4);
memcpy(&outObj.dst, &buf[4], 4);
memcpy(&outObj.ver, &buf[8], 1);
memcpy(&outObj.n, &buf[9], 1);
addr.s_addr = outObj.src;
printf("\nsrc ip = %s", inet_ntoa(&addr));
addr.s_addr = outObj.dst;
printf("\ndest ip = %s", inet_ntoa(&addr));
printf("\nversion = %d", outObj.ver);
printf("\nnumber = %d", outObj.n);
for(i = 0; i < outObj.n; ++i)
{
buflen = 0;
while (buflen < 2)
{
int rc = read(newsockfd, &buf[buflen], 2-buflen);
if (rc <= 0)
{
closesocket(newsockfd);
error("ERROR in read");
}
buflen += rc;
}
memcpy(&outObj.profiles[i].length, &buf[0], 1);
memcpy(&outObj.profiles[i].type, &buf[1], 1);
outObj.profiles[i].data = malloc(outObj.profiles[i].length);
buflen = 0;
while (buflen < outObj.profiles[i].length)
{
int rc = read(newsockfd, &buf[buflen], outObj.profiles[i].length-buflen);
if (rc <= 0)
{
closesocket(newsockfd);
error("ERROR in read");
}
buflen += rc;
}
printf("\nMessage %d :",i+1);
printf("\nLength : %d", outObj.profiles[i].length);
printf("\nType : %d", outObj.profiles[i].type);
for(j = 0; j < outObj.profiles[i].length; j)
printf("\ndata[%d] : %d", j, outObj.profiles[i].data[j]);
}
closesocket(newsockfd);
return 0;
}