I want to make a server that accepts both IPv4 and IPv6 on all interfaces.
It does not seems to work for any address including localhost, 127.0.0.1, ::1, 192.168.1.26.
What am I missing?
According to getaddrinfo(3) since ai_family is set to the AI_PASSIVE flag. 'The returned socket address will contain the "wildcard address"'
Here is my code so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/times.h>
#include <errno.h>
#define MAXBUF 1024
const char* PORTNUM = "687";
int init_address(struct addrinfo* hints)
{
hints->ai_flags= AI_PASSIVE;
hints->ai_family= AF_UNSPEC;
hints->ai_socktype= SOCK_DGRAM;
hints->ai_protocol= IPPROTO_UDP;
return 1;
}
socklen_t init_socket(struct addrinfo* res, int* sockfd)
{
struct addrinfo* ressave;
struct sockaddr_in* all_interface;
socklen_t addrlength;
ressave=res;
all_interface = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
do {/* each of the returned IP address is tried*/
(*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if ((*sockfd)<0)
continue; /* fail, try next one*/
if (bind((*sockfd), (struct sockaddr*)all_interface, sizeof(all_interface)) == 0)
break; /*success*/
close(*sockfd);
}while(res->ai_next != NULL && (res = res->ai_next)!= NULL);
if(&addrlength)
addrlength = res->ai_addrlen;
freeaddrinfo(ressave);
free(all_interface);
return addrlength;
}
int doprocessing(char* buffer, size_t buff_size)
{
return 0;
}
int peak_data(char* buffer, size_t buff_size)
{
return 0;
}
int main(int argc, char const *argv[])
{
int sockfd, newsockfd;
int bytes_read;
char* port;
char buffer[MAXBUF];
pid_t pid;
socklen_t addrlen, len;
struct addrinfo* socket_info;
struct addrinfo* res;
struct addrinfo* backup_res;
struct sockaddr* cliaddr;
int n;
socket_info = (struct addrinfo*)malloc(sizeof(struct addrinfo));
res = (struct addrinfo*)malloc(sizeof(struct addrinfo));
memset(socket_info, 0, sizeof(struct addrinfo));
init_address(socket_info);
if((n = getaddrinfo(NULL, PORTNUM, socket_info, &res)) !=0)
{
printf("multi_server: error for %s: %s", PORTNUM, gai_strerror(n));
exit(0);
}
if ((addrlen = init_socket(res, &sockfd)) < 0)
{
printf("multi_server: Socket or Bind error");
exit(0);
}
free(socket_info);
cliaddr=malloc(addrlen);
len=addrlen;
printf("\nUDP Server: waiting for connection...");
while (1) {
bytes_read = recvfrom(sockfd, buffer, MAXBUF-1, MSG_PEEK, cliaddr, &len);
if (bytes_read > 0) {
// a connection has been established
buffer[MAXBUF] = '\0';
printf("\nUDP Server: received %d bytes ", bytes_read);
pid = fork();
if (pid < 0) {
perror("UDP Server: ERROR while forking new process.\n");
exit(1);
}
// check if the process ID is zero
if (pid == 0) {
// we are now inside the new forked process
if(peak_data(buffer, bytes_read))
{
doprocessing(buffer, bytes_read);
}
printf("Now in %d\n", pid);
close(sockfd);
exit(0);
}
}
}
}
You're not missing anything. It is accepting connections to ::1 you said? Then it will accept ipv6 connections. And since IPv6 is backwards compatible, if you've created the correct ipv6 socket, it should be able to send and receive ipv4 packets as well.
Related
I've just started taking network programming classes and this is what we did in class in order to make connection between client and server. My problem is that I cannot connect to the server, it just stops after printing "addrinfo is successful" and does not loop through.
We used 8080 for port number in class and that did not work, so I tried using 7070 and it worked maybe 1 out of 50 times. I don't have any problems with the client side of the program, it works completely fine. I'm using Visual Studio Code on MacBook if that makes any difference, I also tried using the terminal but that did not work either.
//client to server
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
int main(){
const char *hostname = "127.0.0.1";
const char *portNumber = "7070";
int clientSocket; //socketFD
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
struct addrinfo *results; // const for head
struct addrinfo *record; // temp for traversing
int error;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(hostname, portNumber, &hints, &results);
// error checking
if(error >= 0){
printf("Client: getaddressinfo() successful\n ");
}
//traversing the list
for(record = results; record != NULL; record = record->ai_next){
clientSocket = socket(record->ai_family, record->ai_socktype, 0);
if(clientSocket == -1){
continue;
}
if(connect(clientSocket, record->ai_addr, record-> ai_addrlen) != -1){
break;
}
close(clientSocket);
}
//socket() and connect() both were success
//send()
if(record == NULL){
printf("Error\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(results);
printf("socket status: created and connected\n");
char *message = "Hello" ;
if(send(clientSocket, message, strlen(message), 0) == -1){
printf("Error\n");
exit(EXIT_FAILURE);
}
else{
printf("Message sent successfuly\n");
}
close(clientSocket);
return 0;
}
//server
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
int main(){
printf("Starting the server\n");
const size_t bufferSize = 1024;
const char *portNumber = "7070";
const int backlog = 1;
int serverSocket;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo *results;
struct addrinfo *record;
if((getaddrinfo(NULL, portNumber, &hints, &results)) != 0){
printf("Error\n");
exit(EXIT_FAILURE);
}
printf("addrinfo is successful\n");
//traverse through the list
for(record = results; record != NULL; record = record->ai_next){
serverSocket = socket(record->ai_family, record->ai_socktype, record->ai_protocol);
if(serverSocket == -1){
continue;
}
int enable = 1;
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if(bind(serverSocket, record->ai_addr, record->ai_addrlen) == 0){
break;
}
close(serverSocket);
}
if(record == NULL){
exit(EXIT_FAILURE);
}
freeaddrinfo(results);
printf("Socket status: created and binded successfuly\n");
if(listen(serverSocket, backlog) == -1){
printf("ERROR\n");
exit(EXIT_FAILURE);
}
printf("Server is listening\n");
while(1){
int clientSocket;
struct sockaddr clientAddress;
socklen_t clientAddressLength = sizeof(clientAddress);
if((clientSocket = accept(serverSocket, &clientAddress, &clientAddressLength)) <0){
printf("Error\n");
exit(EXIT_FAILURE);
}
printf("Client socket accepted\n");
char buffer[bufferSize];
if(recv(clientSocket, buffer, sizeof(buffer), 0) == -1){
printf("Error\n");
exit(EXIT_FAILURE);
}
printf("Message is received: %s\n", buffer);
close(clientSocket);
printf("Client socket is closed\n");
}
return 0;
}
So I have one UDP server that returns the hour or the date to the client with the following code:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
void main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *res;
struct sockaddr_storage cli;
time_t rawtime;
struct tm* timeinfo;
char tbuffer[9];
char buf[81], host[NI_MAXHOST], serv[NI_MAXSERV];
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
getaddrinfo(argv[1], argv[2], &hints, &res);
int sd = socket(res->ai_family, res->ai_socktype, 0);
bind(sd, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
while(1) {
socklen_t clen = sizeof(cli);
int c = recvfrom(sd, buf, 80, 0, (struct sockaddr*) &cli, &clen);
buf[c] = '\0';
getnameinfo((struct sockaddr*) &cli, clen, host, NI_MAXHOST, serv, NI_MAXSERV, NI_NUMERICHOST);
time(&rawtime);
timeinfo = localtime(&rawtime);
if(buf[0] == 't') {
printf("%ld bytes de %s:%s\n", c, host, serv);
ssize_t chars = strftime(tbuffer, sizeof(tbuffer), "%T", timeinfo);
sendto(sd, tbuffer, chars, 0, (struct sockaddr *)&cli, clen);
} else if(buf[0] == 'd') {
printf("%ld bytes de %s:%s\n", c, host, serv);
ssize_t chars = strftime(tbuffer, sizeof(tbuffer), "%D", timeinfo);
sendto(sd, tbuffer, chars, 0, (struct sockaddr *)&cli, clen);
} else if(buf[0] == 'q') {
printf("Saliendo...\n");
exit(EXIT_SUCCESS);
} else {
printf("Comando no soportado %s", buf);
}
}
}
To test the code I was using ./server <IPServerAddres> <PortAddress> on the server side and nc -u <IpServerAddress> <PortServer> on the client side (another machine).
Now I want to create the UDP client UDP and do the same without using nc, just writing ./client <IPServerAddres> <PortAddress> <command> where command can be t for time d for date and q for quit, just like in the server.
Here is the code of the client program:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *res, *resp;
int sd, j, s;
size_t len;
ssize_t nread, nwrite;
char buf[500];
if (argc < 3) {
fprintf(stderr, "Usage: %s host port command...\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
getaddrinfo(argv[1], argv[2], &hints, &res);
for(resp = res; resp != NULL; resp = resp->ai_next) {
sd = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
if(sd == -1) {
perror("socket()");
continue;
}
if(connect(sd, resp->ai_addr, resp->ai_addrlen) == -1) {
perror("socket()");
} else {
break;
}
close(sd);
}
freeaddrinfo(res);
for(j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
nwrite = write(sd, argv[j], len);
if(nwrite == -1) perror("write()");
nread = read(sd, buf, 500);
buf[nread] = 0;
if(nread == -1) perror("read()");
printf("Recibidos %ld bytes: %s\n", (long) nread, buf);
}
exit(EXIT_SUCCESS);
}
The problem is that when I try to run my client program I got no response, so I guess is in a infinite loop or something like that.
Any help will be apreciated, I'm learning C so I'm sorry for the mistakes, thank you.
EDITED: Corrected the break in the for loop in case connect() returns something different than -1.
The problem is in your calculation of the length of the message to send:
len = strlen(argv[j] + 1);
This gets the length of the string starting from the second character. You want:
len = strlen(argv[j]) + 1;
This gives you the string length plus 1 for the null terminator.
Also, after reading the response, you'll need to null-terminate what you got back:
buf[nread] = 0;
I'm making a client-server program in C using threads.
I've got this problem: on the server, on thread #1 (number_one), function "read" works fine. But when I create another thread #2 (number_two), on this one something goes wrong. Parameters are passed in the right way (I think).
-->thread number_one
...
char message[256];
int new_connection=accept(master_sock,NULL,NULL);
pthread_t temp
if(pthread_create(&temp , NULL , number_two , (void*) &new_connection))
{
perror("pthread_create failed");
exit(-2);
}
else
{
puts("number_two created");
if(read(new_connection, message, 256) > 0)
printf("Message from client is %s", message);
}
if(pthread_detach(temp))
{
perror("detach failed");
exit(-3);
}
...
---> thread number_two
void *number_two(void *sock_desc)
{
int sock = *(int*)sock_desc;
int read_size;
char client_message[2000];
read_size=read(sock, client_message, 256);
client_message[read_size]='\0';
return 0;
}
In "number_one", read waits an input from the client, and then it sets correctly the buffer "message".
In "number_two", read does not wait the client and does not set the buffer "client_message".
Thank you.
Please try my code? it works, I think it is the same with your code.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define INVALID_SOCKET_FD (-1)
int create_tcp_server_socket(unsigned short port, bool bind_local, int backlog,
char *caller_name)
{
int socket_fd = INVALID_SOCKET_FD;
struct sockaddr_storage server_addr;
unsigned int yes = 1;
// just try ipv4
if (socket_fd < 0 && (socket_fd = socket(PF_INET, SOCK_STREAM, 0)) >= 0) {
struct sockaddr_in *s4 = (struct sockaddr_in *)&server_addr;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
memset(&server_addr, 0, sizeof(server_addr));
s4->sin_family = AF_INET;
s4->sin_port = htons(port);
if (bind_local)
s4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
else
s4->sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(socket_fd, (struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
close(socket_fd);
printf("Server: Failed to bind ipv4 server socket.\n");
return INVALID_SOCKET_FD;
}
}
else if (socket_fd < 0) {
printf("Server: Failed to create server socket.\n");
return INVALID_SOCKET_FD;
}
if (listen(socket_fd, backlog) < 0) {
close(socket_fd);
printf("Server: Failed to set listen.\n");
return INVALID_SOCKET_FD;
}
return socket_fd;
}
pthread_t temp;
void *number_two(void *sock)
{
char buf[1024];
int fd = *(int *)sock;
int nread = read(fd, buf, 1024);
write(STDOUT_FILENO, buf, nread);
return NULL;
}
int main()
{
pid_t pid;
if ((pid = fork()) < 0) {
}
else if (pid > 0) { // parent, server
char buf[1024];
int fd = create_tcp_server_socket(8787, false, 10, "zz");
int new_fd = accept(fd, NULL, 0);
pthread_create(&temp, NULL, number_two, (void *)&new_fd);
}
else { // child, client
uint32_t ip;
struct hostent *hp = gethostbyname("localhost");
memcpy(&ip, hp->h_addr_list[0], hp->h_length);
struct sockaddr_in server_addr;
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = ip;
server_addr.sin_port = htons(8787);
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
write(fd, "abcd", 4);
}
pause();
return 0;
}
I'm trying to make a server and client. But when I try to connect the client to the server, I get connection refused. The other answers on stack overflow said to make sure you have listen() and accept(), which I do, and to check the firewalls. So I turned off all the firewalls just to make sure.
I still get connection refused, so I tried ./telnet 10.1.10.13 9696, and got:
Trying 10.1.10.13...
telnet: connect to address 10.1.10.13: Connection refused
telnet: Unable to connect to remote host
Here's the code for the server
int setUpServer(struct fuzzerObj *ptr)
{
/* Declarations */
int hostSocket, yes = 1, rtrn;
union
{
struct sockaddr_in in;
}address;
/* Create Socket */
hostSocket = socket(AF_INET, SOCK_STREAM, 0);
if(hostSocket < 0)
{
errorHandler("Could not create socket\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* Reuse Address */
rtrn = setsockopt(hostSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(rtrn < 0)
{
errorHandler("Couldn't Reuse Address\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
errno = 0;
/* Set Up Struct */
address.in.sin_len = sizeof(address.in);
address.in.sin_family = AF_INET;
address.in.sin_port = BBPORT_NUMBER;
address.in.sin_addr.s_addr = htonl(INADDR_ANY);
memset(address.in.sin_zero, 0, sizeof(address.in.sin_zero));
/* Bind Address to Socket */
rtrn = bind(hostSocket, (struct sockaddr*) &address, address.in.sin_len);
if(rtrn < 0)
{
errorHandler("Can't Bind Address to Socket\n", FUNCTION_ID_SET_UP_SERVER);
perror("");
return -1;
}
/* listen */
rtrn = listen(hostSocket, ptr->numberOfClients);
if(rtrn < 0)
{
errorHandler("Can't Listen\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
while(1) acceptClient(hostSocket);
return 0;
}
int acceptClient(int fd)
{
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
int clientFd = accept(fd, (struct sockaddr *) &addr, &addr_len);
if(clientFd < 0)
{
printf("Can't Accept Client\n");
return -1;
}
return clientFd;
}
and the code for the client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#define BLACKBOX_PORT 9696
int main(int argc, char *argv[])
{
/* Check To See If an argument was passed */
if(argc < 2)
{
printf("No enough Arguments\n");
return -1;
}
/* Declaration's */
const char *ip = argv[1];
int sockfd, fd, rtrn;
char *inBuf;
struct sockaddr_in servaddr,cliaddr;
socklen_t len = sizeof(cliaddr);
/* Get Socket to Connect to Fuzz Server */
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("Can't Create Socket");
return -1;
}
/* Fill Out Struct */
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(BLACKBOX_PORT);
inet_pton(AF_INET, ip, &servaddr.sin_addr);
/* Attempt Connection */
fd = connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
if(fd < 0)
{
perror("Can not connect to BlackBox Fuzz server");
return -1;
}
/* Allocate Space in Memory for Incoming Connection */
inBuf = (char *) malloc(1025);
if(inBuf == NULL)
{
perror("Mem Error");
return -1;
}
/* Read From Socket */
rtrn = read(fd, inBuf, 1024);
if(rtrn < 0)
{
perror("Can't Read Data From BlackBox Server");
return -1;
}
printf("Received Data: %s\n", inBuf);
free(inBuf);
return 0;
}
Output from client:
./client 10.1.10.13
Can not connect to BlackBox Fuzz server
Connection refused
Any help would be appreciated, thanks.
Assuming that you're running this code on a little-endian machine, you need to use htons() when assigning the port number on the server side too.
(On big-endian machines htons() is a "no-op", but you should always use it to ensure portability)
I need to transder a file from one application to another application on the same machine. I wrote code which transfers a packet structure which has fields like:
seq no
round
data, which is an unsigned char indicating the data to be transferred
length, which indicates how many bytes have been read using the read function
crc, which is default string as of now
and a parameter, last, indicating that it is the last packet so that the file and connection can be closed.
This code works perfectly for ASCII files, but, when I use it to transfer a binary file, the diff of two files don't match. I am not able to figure out what the problem is. Can some one help me?
Here is the code for my sender. It connects to receiver on port 4950.
#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 <arpa/inet.h>
#include <netdb.h>
#define DATA 170
#define SERVERPORT "4950" // the port users will be connecting to
typedef struct packet_ {
unsigned short int seq;
unsigned short int round;
unsigned short int last;
unsigned short int length;
unsigned char data[DATA];
unsigned char crc[17];
} packet;
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
int max_seq_no = 10;
packet send;
FILE *fp;
unsigned short int seq =0, round =0;
long int totalBytes = 0;
unsigned short int bytes_read =0;
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
fp = fopen("wilde-tiobe.txt", "rb");
printf("Size of packet : %d", sizeof send);
while (1) {
memset((void *) &send, '\0', sizeof send);
send.seq = seq;
send.round = round;
memset(send.data, '\0', DATA);
bytes_read = read(fileno(fp), send.data, DATA );
send.length = bytes_read;
if (bytes_read < DATA) {
send.last = 1;
printf("****last byte***\n");
}
strcpy(send.crc, "yet to calcula\0");
totalBytes+= bytes_read;
//if(bytes_read == 0) break;
if ((numbytes = sendto(sockfd, &send, sizeof send, 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
usleep(60000);
if (send.last) break;
}
fclose(fp);
printf("Total bytes transferred : %lu\n", totalBytes);
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
and here is the code for my receiver :
#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 <arpa/inet.h>
#include <netdb.h>
#define MYPORT "4950" // the port users will be connecting to
#define MAXBUFLEN 196
#define DATA 170
typedef struct packet_ {
unsigned short int seq;
unsigned short int round;
unsigned short int last;
unsigned short int length;
unsigned char data[DATA];
unsigned char crc[17];
} packet;
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
FILE *fp;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
packet * recv, recv_packet;
fp = fopen("wtf.bmp", "wb");
printf("size of packet :%d", sizeof(packet));
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
freeaddrinfo(servinfo);
addr_len = sizeof their_addr;
while(1) {
printf("listener: waiting to recvfrom...\n");
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN , 0,
(struct sockaddr *)&their_addr,
&addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
printf("listener: got packet from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s));
printf("listener: packet is %d bytes long\n", numbytes);
//printf("listener: packet contains \"%s\"\n", buf);
recv = (packet *) buf;
if (!recv_packet.data) {
printf("NO memory\n");
break;
}
memset(&recv_packet, 0, sizeof recv_packet);
recv_packet.seq = recv->seq;
recv_packet.round = recv->round;
recv_packet.last = recv->last;
recv_packet.length = recv->length;
memset(recv_packet.data, '\0', DATA);
strncpy(recv_packet.data, recv->data, recv_packet.length);
strncpy(recv_packet.crc, recv->crc, 17);
//printf(" len: %hu and data: %s \n", recv_packet.length, recv_packet.data);
write(fileno(fp), recv_packet.data, recv_packet.length);
if (recv_packet.last) {
printf("Last packet\n");
break;
}
}
fclose(fp);
close(sockfd);
return 0;
}
I already had a similar problem with socket because I was sending a buffer of "unsigned char[]", and receiving into a buffer of "char[]", I dont think is your problem because you do not do any manipulation within the signed array, but any way is good to avoid those casts, and it worth the shot.
use
unsigned char buf[MAXBUFLEN];
instead of
char buf[MAXBUFLEN];
Also clear your buffer before receiving the packet, and check the value of "numbytes" before continuing the process.
Example:
printf("listener: waiting to recvfrom...\n");
memset(buff, 0, sizeof(buff));
numbytes=0;
while ( (numbytes += recvfrom(sockfd, &buf[numbytes], MAXBUFLEN - numbytes , 0,
(struct sockaddr *)&their_addr,
&addr_len)) < sizeof(packet))
printf("Oops, the package is not full, lets read it again.");
}
Or try to pass the MSG_WAITALL flag when using recvfrom to read entire blocks of memory, but I still prefer to check the amount of data read every time.