I'm writing a code for my project in C. I need to add a loop so that the ip_address can be passed to inet_addr() from the array and I can print the send & receive the data. But my code is only executing till printf("Send \n") and I'm not receiving anything after that. The program seems to just hang up & I'm not getting any errors too. Also, the code is running fine when I'm hardcoding the address(eg."100.12.1.10") directly. I tried various methods but nothing seems to be working. I can't figure it out.
It would be great if you guys have any suggestions.
PS: This is only a part of the whole code and other parts are working fine.
unsigned char *ip_address[25] = { "879.120.8.249",
"232.106.122.6",
"17.105.176.86",
"85.195.823.169", ......}
for(int k = 0; k < 25; k++) {
size_t l = strlen(ip_address[k]);
char address[l];
//address = (char*)malloc(l);
memcpy(address, ip_address[k], l+1);
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_addr.s_addr = inet_addr(address);
//printf("Ip_address = %s\n", ip_address[k]);
//printf("address = %s\n", address);
int n, len=0;
for(i=0;i<MAXLINE;i++){
len++;
if(buffer[i]==62 && buffer[i-1]==62)
break;
}
printf("Len = %d\n", len);
printf("Send \n");
sendto(sockfd, (const char *)buffer, len,
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("before Receive");
n = recvfrom(sockfd, (char *)recv_buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &servaddr,
&len);
printf("after receive");
for(i=0;i<n;i++){
printf("%d,", recv_buffer[i]);
}
printf("\n");
close(sockfd);
}
At least these problems:
Insufficient space
// char address[l]; // too small
char address[l+1];
memcpy(address, ip_address[k], l+1);
Index of -1?
buffer[] not defined, yet buffer[0-1] looks strange
for(i=0;i<MAXLINE;i++){
len++;
if(buffer[i]==62 && buffer[i-1]==62)
break;
}
Perhaps
//if(buffer[i]==62 && buffer[i-1]==62)
if(i > 0 && buffer[i]==62 && buffer[i-1]==62)
Well, I got it working today somehow.
unsigned char *ip_address[25] = { "879.120.8.249",
"232.106.122.6",
"17.105.176.86",
"85.195.823.169", ......};
Here, I changed the unsigned char to const char, then used the variable directly, and it worked somehow.
servaddr.sin_addr.s_addr = inet_addr(ip_address[k]);
Related
I am trying to use the same pointer twice, like this:
void* pointer = (char*) malloc(15);
pointer = "Patricia";
printf("%s", pointer);
pointer = "John";
printf("%s", pointer);
but the output I'm receiving is this:
Patricia
Johnicia
Here is the full code (the client script is a python script so I don't find it appropriate to post here)(the John and Patricia are examples of usernames the client might enter):
#define MAXCLIENTS 256
#define MAXMSG 269
void forward(int clientslist[MAXCLIENTS], char* msg) {
int x;
for (x=0; x < MAXCLIENTS; x++){
send(clientslist[x], msg, MAXMSG, 0);
}
return;
}
int main(){
#define PORT 5943
int s = socket(AF_INET, SOCK_STREAM, 0);
int clients[MAXCLIENTS];
int clientcounter = 0;
fd_set socketlist, readlist;
FD_ZERO(&socketlist);
FD_SET(s, &socketlist);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
bind(s, (struct sockaddr*) &server, sizeof(server));
listen(s, MAXCLIENTS);
int clientsocket;
int i;
void* msg = (char *) malloc(MAXMSG);
void* usr = (char*) malloc(10);
while (1){
readlist = socketlist;
select(FD_SETSIZE, &readlist, NULL, NULL, NULL);
for (i=0; i<FD_SETSIZE; i++){
if(FD_ISSET(i, &readlist)){
if (i == s){
clientsocket = accept(s, NULL, NULL);
FD_SET(clientsocket, &socketlist);
clients[clientcounter] = clientsocket;
clientcounter++;
recv(clientsocket, usr, 10, 0);
printf("Connection received from %s\n", usr);
} else {
recv(i, msg, MAXMSG, 0);
forward(clients, msg);
}
}
}
}
return 0;
}
How do I fix this??
Thanks
recv returns the number of bytes read, and you just need to add a null terminator. eg:
ssize_t rc;
rc = recv(clientsocket, usr, 9, 0);
if( rc >= 0 )
usr[rc] = '\0';
Note that I've reduced the length argument in the call to recv to ensure that there is space for the terminator. If you expect to receive messages of length 10, you would want to allocate at least 11 bytes for usr. However, with buffers that small, it would probably be cleaner to use an array and do:
char usr[11];
ssize_t rc;
rc = recv(clientsocket, usr, sizeof usr - 1, 0);
if( rc >= 0 )
usr[rc] = '\0';
I'm trying to read data from a UDP socket, but after reading the first 255 bytes, read() seems to drop the rest of the data on the socket and block until another data-gram comes in.
Here's the network code I'm using:
int sock;
struct sockaddr_in remote_addr, self_addr;
uint8_t network_init(uint16_t port)
{
memset((char *) &remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_addr.s_addr = inet_addr("192.168.1.22");
remote_addr.sin_port = htons(3001);
memset((char *) &self_addr, 0, sizeof(self_addr));
self_addr.sin_family = AF_INET;
self_addr.sin_addr.s_addr = INADDR_ANY;
self_addr.sin_port = htons(3001);
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
fprintf(stderr, "Could not create socket.");
return 1;
}
else if (bind(sock, (struct sockaddr *) &self_addr, sizeof(self_addr)) != 0)
{
fprintf(stderr, "Could not bind to socket.");
return 1;
}
return 0;
}
void network_send(uint8_t *data, uint8_t len)
{
sendto(sock, data, len, 0, (struct sockaddr *) &remote_addr, sizeof(remote_addr));
}
void read_data()
{
int len = 0;
ioctl(sock, FIONREAD, &len);
// We have data
if (len > 0)
{
char *buffer = (char *) malloc(256);
uint8_t buflen;
printf("==== %d | Data:\n", len);
while (len > 0)
{
buflen = min(255, len);
len = len - buflen;
buffer[buflen] = '\0';
printf("len: %d, buflen: %d,\n",len, buflen);
read(sock, buffer, buflen);
printf("%s\n", buffer);
}
printf("\n");
}
}
Here's the command I'm using to send data:
echo -n '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' | nc -u localhost 3001
And here's the output:
==== 257 | Data:
len: 2, buflen: 255,
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
len: 0, buflen: 2,
^C
Also, after performing this read, ioctl(sock, FIONREAD, &len); produces a length result of 0. My suspicion is that for some reason, read() is clearing out the rest of the data before it has a chance to be read, but I can't seem to find any reference to this behaviour in any documentation.
I'm developing on an Ubuntu linux machine (x86_64).
With UDP sockets, each call to read() reads a whole datagram out of the kernel. If the read buffer isn't big enough for the entire datagram, the rest of it will be discarded. It's not like a stream socket, where you can keep calling until you get everything.
Since FIONREAD tells you the number of bytes in the message, you should use that as the size to malloc() rather than using 256:
if (len > 0) {
char *buffer = malloc(len);
...
P.S. Do I cast the result of malloc?
I have the following structure in my header file structure.h. Now i need to use this structure in my main.c file.
I need to fill this structure with some values and I need to send this from TCP/IP client to the TCP/IP server on the same system.
#ifndef STRUCTURE_H
#define STRUCTURE_H
typedef struct
{
unsigned int variable3;
char variable4[8];
}NUMBER_ONE,*PNUMBER_ONE;
typedef struct
{
unsigned int variable5;
char variable6[8];
}NUMBER_TWO,*PNUMBER_TWO;
typedef struct
{
char name[32];
unsigned int a;
unsigned int b;
NUMBER_ONE variable1;
NUMBER_TWO variable2;
}NUMBER_THREE,*PNUMBER_THREE;
#endif
I have tried this but, I am not good in C, so please can anyone tell me how to do it, by taking the above structure as an example? Till socket connection establishment is ok for me,
but after establishing connection, how do I send this structure from the client to the server?
I am doing this in my Linux Ubuntu 12.04 system.
When sending information using sockets three ways used:
1)fixed size message (we will use it, plus assuming we are writing on the same machine byteorder match).Simply, like we will send 100 bytes and on receive we will read 100bytes
2)message.len + message.( first we send message len then message itself. used for binary send receive mostly)
3)marker method (mostly used sending text messages or commands. for exampling marking with \n newline)
Next coming on representing our data (serialize). It is easy with c cause on c we can directly write our object and retrieve it without additional efforts.Object will be the same as in memory.
// PNUMBER_THREE structAddr;
send(socket_id, structAddr, sizeof(NUMBER_THREE), 0);
or
write(socket_id, structAddr, sizeof(NUMBER_THREE));
or safer
write_socket(socket_id, structAddr, sizeof(NUMBER_THREE));
//It is safer to do so though we are using blocking mode
int write_socket(int fd,const char *buf,int len){
int currentsize=0;
while(currentsize<len){
int count=write(fd,buf+currentsize,len-currentsize);
if(count<0) return -1;
currentsize+=count;
}
return currentsize;
}
when reading we will be using the same structure plus it must meet condition sizeof(NUMBER_THREE)==SizeInsideClient //SizeInsideClient is sizeof on client SizeInsideClient=sizeof(NUMBER_THREE)
//SizeInsideClient structure size on client program
assert(sizeof(NUMBER_THREE)==SizeInsideClient);
readblock(socket_id,structAddr,sizeof(NUMBER_THREE));
int readblock(int fd, char* buffer, int len) {
int ret = 0;
int count = 0;
while (count < len) {
ret = read(fd, buffer + count, len - count);
if (ret <= 0) {
return (-1);
}
count += ret;
}
return count;
}
Short example with no error checking:
Server
struct sockaddr_in serv_addr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
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);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
Client
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(5000);
inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);
connect(sockfd,
(struct sockaddr *)&serv_addr, sizeof(serv_addr))
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
Pitfalls
Is not "safe" so send plain struct. Sooner or later you will deal with endianness (byte order), packing (which can still be a problem even with #pragma pack) and sizes of types like 'int' that can vary between platforms
I need to send a message to a client and then the client have to respond with an option. I get till the client and server connects, but both program end with "Segmentation Fault". Does anyone knows what this error means? Can someone give an idea to how to create a code that will make client and server interact. After receiving the option chosen by the client the server have to analyze it and send again a result to client.
My codes are:
Server
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
char message[MAXLINE]="This is the server";
char temp_scale[2];
char recvdata[MAXLINE + 1];
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*----------------------------------------------------*/
servaddr.sin_port = htons(5555);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; )
{
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("Connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
snprintf(message, sizeof(message), "%s\r\n");
Writen(connfd, message, strlen(message));
while ( (n = read(connfd, recvdata, MAXLINE)) > 0)
{
recvdata[n] = 0; /* null terminate*/
if (fputs(recvdata, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
Close(connfd);
}
}
Client
int
main(int argc, char **argv)
{
int sockfd, rd;
socklen_t len;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr, cliaddr;
char scale[2];
/*if (argc != 2)
err_quit("usage: a.out <IPaddress>");*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2])); /*port passed through command line*/
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) /*The client translates the server address, passed on the command line*/
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
len = sizeof(cliaddr);
Getsockname(sockfd, (SA *) &cliaddr, &len);
printf("Local Address is: %s\n",
Sock_ntop((SA *) &cliaddr, sizeof(cliaddr)));
printf("Iniciando read...\n");
while ( (rd = read(sockfd, recvline, MAXLINE)) > 0)
{
recvline[rd] = 0; /* null terminate*/
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (rd < 0)
err_sys("read error");
printf("Enter option 'A' or 'B'");
send_scale(sockfd);
exit(0);
}
Thanks
Your server is probably faulting because of this:
snprintf(message, sizeof(message), "%s\r\n"); // <== no parameters
It is flat-out wrong. The snprintf() call has a format specifier that is expecting a char * to a null-terminated string, and you're passing it absolutely nothing. It is therefore grabbing a random value out of the stack, treating it as a pointer, and dereferencing it in attempt to fulfill the formatted request.
Without knowing the details of the API you're using (it clearly isn't standard BSD sockets just by the names alone) there isn't much more to go on.
Run your code in a debugger (for example gdb ./a.out) and find out in no time.
I don't know if it might help, but in C the null termination for strings is '\0', when you print your response:
recvdata[n] = 0; /* null terminate ----> this must be '\0'*/
if (fputs(recvdata, stdout) == EOF)
err_sys("fputs error");
you pad it whith a "0", so it will probably lead you to a segfault when fputs parse your string in order to print it.
Hope it helps!
I am writing a simple messaging application in C using sockets. When I use function recvfrom, it returns -1 and sets errno = 14 which is Bad address (which I am printing at the end).
The strange thing is that it still reads from the socket and gets the correct message. That is, the application is working perfectly and as expected except for that error.
My question is this: Why do you think I am getting this error? I cannot think of any reason. I was using inet_pton to set peer->sin_addr but I was getting the same error.
// socket file descriptor to send data through
int recv_sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
// fill in the peer's address, loopback in this case
struct sockaddr_in *peer = malloc(sizeof(struct sockaddr_in));
peer->sin_family = AF_INET;
peer->sin_port = htons(11110);
char *new = &(peer->sin_addr);
new[0] = 127;
new[1] = 0;
new[2] = 0;
new[3] = 1;
for (int i = 0; i < 8; i++) {
peer->sin_zero[i] = NULL;
}
bind(recv_sock_fd, peer, sizeof(struct sockaddr_in));
// check to see if the socket has any data...code removed
char buff[32] = {0};
errno = 0;
int bytes_received = recvfrom(recv_sock_fd, buff, sizeof(buff), NULL, (struct sockaddr *)peer, sizeof(struct sockaddr_in));
printf("Bytes recieved: %d: %d : %s\n", bytes_received, errno, strerror(errno));
Look at the signature of recvfrom(2):
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
Last argument is an address, while you are giving it a plain integer.
Then you're building of the IP address is wrong. Do use inet_pton(3), that's what it's for. Also check the return value of the bind(2), it's surely failing now.