compressing multicast packets with zlib library - c

I am listening packets from a multicast ip port and trying to compress that packet using zlib library, ( want to know the compression ratio from zlib in the live packets, as this is the requirement from our client). I have implemented zlib compression code as below, but length of outputDataBuffer is not printing correct, I dont know what I am missing.
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <zlib.h>
using namespace std;
struct sockaddr_in localSock;
struct ip_mreq group;
int maxpacketsize = 1500;
void connectSocket(int &sd,char *multicastIP,int multicastPort,char *interfaceIP);
void listenSocket(int &sd,const short &structureSize,const short &compressionType);
void compressZlib(char *inputDataBuffer,int inputDataLength,z_stream &defstream)
int main(int argc, char *argv[])
{
int sd = 0;
char multicastIP[16]="230.0.0.50";
char interfaceIP[16]="192.168.225.132";
int multicastPort = 13551;
short structureSize = 0;
connectSocket(sd,multicastIP,multicastPort,interfaceIP);
listenSocket(sd,structureSize);
return 0;
}
void connectSocket(int &sd,char *multicastIP,int multicastPort,char *interfaceIP)
{
int reuse = 1;
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
printf("Opening datagram socket....OK.\n");
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);
}
printf("Setting SO_REUSEADDR...OK.\n");
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(multicastPort);
localSock.sin_addr.s_addr = INADDR_ANY;
if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(sd);
exit(1);
}
printf("Binding datagram socket...OK.\n");
group.imr_multiaddr.s_addr = inet_addr(multicastIP);
group.imr_interface.s_addr = inet_addr(interfaceIP);
if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(sd);
exit(1);
}
printf("Adding multicast group...OK.\n");
}
void compressZlib(char *inputDataBuffer,int inputDataLength,z_stream &defstream)
{
char *outputDataBuffer = new char[inputDataLength];
memset(outputDataBuffer,0,inputDataLength);
defstream.avail_in = (uInt)strlen(inputDataBuffer)+1;
defstream.next_in = (Bytef *)inputDataBuffer;
defstream.avail_out = (uInt)sizeof(outputDataBuffer);
defstream.next_out = (Bytef *)outputDataBuffer;
if(deflate(&defstream, Z_FINISH) != Z_OK )
{
cout<<"Error"<<endl;
}
//printf("%lu %lu\n", inputDataLength,defstream.total_in);
printf("%lu %lu\n", inputDataLength,strlen(outputDataBuffer));
}
void listenSocket(int &sd,const short &structureSize)
{
char databuf[5000] = "";
int receivedBytes = 0;
z_stream defstream;
defstream.zalloc = Z_NULL ;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
deflateInit(&defstream, Z_FULL_FLUSH);
while(1)
{
int socklen = sizeof(struct sockaddr_in);
struct sockaddr_in saddr;
receivedBytes = recvfrom(sd, databuf, maxpacketsize, 0, (struct sockaddr *)&saddr, (socklen_t*)&socklen);
if(receivedBytes < 0)
{
perror("Reading datagram message error");
close(sd);
exit(1);
}
compressZlib(databuf,receivedBytes,defstream);
//compressZlib(databuf1,strlen(databuf1));
//compressZlib();
//cout<<receivedBytes<<endl;
}
deflateEnd(&defstream);
}
I also used compress2() function which is as below:
compress2((unsigned char*)outputBuffer,&outputDataLength,(const unsigned char*)inputBuffer,(unsigned long)inputBufferLength,Z_DEFAULT_COMPRESSION);
but this is also not working, outputDataLength is 0 all the time.

Calling deflate() with Z_FINISH means that you are or have already fed deflate the last of the input data. deflate will then terminate the stream. Once it has been provided enough output space to write the last of the compressed data, which may very well be on the first such call, deflate() will return Z_STREAM_END, not Z_OK. Then the deflate() engine is done and can't be used again unless you do a deflateEnd() followed by a deflateInit(), or equivalently and faster, a deflateReset().
It would seem that what you are missing are the rewards that come from having read the documentation.

Related

Problems with UDP sockets and threads

I've run into a problem with UDP sockets.
For this particular program, a single .c file needs to be both a client to another server (via TCP) and a server/client to itself (executed twice, running on separate servers). It will be running twice at the same time and since it needs to be able to do both the TCP connection (for one type of data) and the UDP connection (for a different type of data) at the same time it needed to be done with threads or forks, but I used threads.
The issue I'm having is the UDP sockets aren't receiving any datagrams from each other. There are no compilation errors and it runs fine, but there's no output other than general debugging print statements. It's getting stuck at the recvfrom commands.
The code below is separated into two parts (again, within the same .c file). The top portion is the server section, and the lower portion is the client section. This is all done WITHIN a thread. I tried creating the socket THEN calling the thread with the client code (the idea was the thread would communicate with the parent but it didn't matter), but it gets the same result. So, for now, the thread just handles the UDP connection and the parent deals with the TCP.
If you need any more explanation, please feel free to ask. This is for a school assignment so I can't give TOO much, but I'll say what I can.
Thank you!
QUICK EDIT: All this code below is doing is just sending hello to the server and back to the client. Further details are not needed.
Assume that argv->stuff is the struct that I passed to the thread and that the user provides the server, IP address, and port when executing.
//----- Server portion of code is below
int cli2_sockfd;
char buffer_cli2[MAXLINE];
char *hello2 = "Hello from client 2";
struct sockaddr_in cli2_addr, client1_addr;
int clis_portno = atoi(argv->port);
clis_portno = clis_portno + 1;
// Creating socket file descriptor
if ( (cli2_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&cli2_addr, 0, sizeof(cli2_addr));
memset(&client1_addr, 0, sizeof(client1_addr));
// Filling server information
cli2_addr.sin_family = AF_INET; // IPv4
cli2_addr.sin_addr.s_addr = INADDR_ANY;
cli2_addr.sin_port = htons(clis_portno);
// Bind the socket with the server address
if ( bind(cli2_sockfd, (const struct sockaddr *)&cli2_addr,
sizeof(cli2_addr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while(1)
{
int n2;
socklen_t len2;
if((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2)) < 0)
{
perror("svr recvfrom");
exit(EXIT_FAILURE);
}
buffer_cli2[n2] = '\0';
printf("Client 1: %s\n", buffer_cli2);
if(sendto(cli2_sockfd, (const char *)hello2, strlen(hello2),
MSG_CONFIRM, (const struct sockaddr *) &client1_addr,
len2) < 0)
{
perror("svr sendto");
exit(EXIT_FAILURE);
}
printf("Hello message sent.\n");
}
//----- The client portion of the code is below
int client1_sockfd;
char buffer[MAXLINE];
char *hello1 = "Hello from client 1";
struct sockaddr_in client2_addr;
struct hostent *client_2;
clis_portno = atoi(argv->port);
clis_portno = clis_portno + 1;
// Creating socket file descriptor
if ( (client1_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&client2_addr, 0, sizeof(client2_addr));
if((client_2 = gethostbyname(argv->name)) == NULL)
{
perror("cli gethostbyname");
exit(EXIT_FAILURE);
}
bzero((char *) &client2_addr, sizeof(client2_addr));
// Filling Client 2 information
client2_addr.sin_family = AF_INET;
bcopy((char *)client_2->h_addr, (char *)&client2_addr.sin_addr.s_addr, client_2->h_length);
client2_addr.sin_port = htons(clis_portno);
while(1)
{
int n1;
socklen_t len1;
if( sendto(client1_sockfd, (const char *)hello1, strlen(hello1),
0, (const struct sockaddr *) &client2_addr,
sizeof(client2_addr)) < 0)
{
perror("cli sendto");
exit(EXIT_FAILURE);
}
printf("IN THREAD: Hello1 = %s\n", hello1);
if((n1 = recvfrom(client1_sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &client2_addr,
&len1)) < 0)
{
perror("cli recvfrom");
exit(EXIT_FAILURE);
}
buffer[n1] = '\0';
printf("IN THREAD: Client 2 : %s\n", buffer);
}
You are forgetting to initialize len2:
socklen_t len2;
if((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2)) < 0)
Better:
socklen_t len2 = sizeof(client1_addr);
n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2));
if (n2 < 0)
{
….
Not sure if that's your only issue that's preventing packets from being received.
I cleaned up your code a little and got it to work using port 9999 for server. And having the client connect to localhost. I cleaned up some of those memcpy statements around gethostbyname, some of your struct initialization calls, removed some of the exit calls that could occur for benign errors (including recvfrom errors when the server is offline). That MSG_WAITALL flag looked weird, so I removed that as well.
I got it working Cygwin without any special hacks. I have no doubt it would work in Linux (or any Unix).
You can see it working here in server mode:
And the corresponding window in client mode:
Code here:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <stdarg.h>
#define MAXLINE 260
#define MSG_CONFIRM "Confirm"
void server(unsigned short port)
{
int cli2_sockfd = -1;
char buffer_cli2[MAXLINE] = { 0 };
char *hello2 = "Hello from client 2";
struct sockaddr_in cli2_addr = { 0 }, client1_addr = { 0 };
unsigned short clis_portno = port;
// Creating socket file descriptor
if ((cli2_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// Filling server information
cli2_addr.sin_family = AF_INET; // IPv4
cli2_addr.sin_addr.s_addr = INADDR_ANY;
cli2_addr.sin_port = htons(clis_portno);
// Bind the socket with the server address
if (bind(cli2_sockfd, (const struct sockaddr *)&cli2_addr,
sizeof(cli2_addr)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while (1)
{
int n2;
socklen_t len2 = sizeof(client1_addr);
if ((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, (struct sockaddr *) &client1_addr,
&len2)) < 0)
{
perror("svr recvfrom");
exit(EXIT_FAILURE);
}
buffer_cli2[n2] = '\0';
printf("Client 1: %s\n", buffer_cli2);
if (sendto(cli2_sockfd, (const char *)hello2, strlen(hello2),
0, (const struct sockaddr *) &client1_addr,
len2) < 0)
{
perror("svr sendto");
}
printf("Hello message sent.\n");
}
}
void client(const char* hostname, unsigned short port)
{
int client1_sockfd;
char buffer[MAXLINE];
char *hello1 = "Hello from client 1";
struct sockaddr_in client2_addr = { 0 };
struct hostent *client_2 = NULL;
unsigned short clis_portno = port;
// Creating socket file descriptor
if ((client1_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
if ((client_2 = gethostbyname(hostname)) == NULL)
{
perror("cli gethostbyname");
exit(EXIT_FAILURE);
}
// Filling Client 2 information
client2_addr.sin_family = AF_INET;
client2_addr.sin_port = htons(clis_portno);
memcpy(&client2_addr.sin_addr, client_2->h_addr, 4);
while (1)
{
int n1;
if (sendto(client1_sockfd, (const char *)hello1, strlen(hello1),
0, (const struct sockaddr *) &client2_addr,
sizeof(client2_addr)) < 0)
{
perror("cli sendto");
exit(EXIT_FAILURE);
}
printf("IN THREAD: Hello1 = %s\n", hello1);
socklen_t len1 = sizeof(client2_addr);
if ((n1 = recvfrom(client1_sockfd, (char *)buffer, MAXLINE,
0, (struct sockaddr *) &client2_addr,
&len1)) < 0)
{
perror("cli recvfrom");
}
else
{
buffer[n1] = '\0';
printf("IN THREAD: Client 2 : %s\n", buffer);
}
sleep(1);
}
}
int main(int argc, char** argv)
{
if ((argc > 1) && (strcmp(argv[1], "s") == 0))
{
printf("Running in server mode\n");
server(9999);
}
else
{
printf("Running in client mode\n");
client("localhost", 9999);
}
return 0;
}

Send 100,000 UDP Packets to Client (C Socket Programming)

I'm working on a cool project and I need to send 100,000 UDP Packets from a Server to a Client with a Packet-to-Packet Delay of 10ms. The Server is Debian Server with a public IP Address. The Client is an other Debian PC with LTE USB-Modem. The Client has no public IP Address and knows the public IP Address of my Server. My 4G/LTE Provider doesn't provide public IP Adresses to thier clients.
I need to build a stable UDP Socket Connection but I'm struggling keeping the socket connection alive.
Can somebody help me?
thx
best regards
/**** CLIENT ****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 20009
int main()
{
int sock;
int size;
int nbytes, flags;
int i;
int a = 0;
char * cp;
char buffer[] = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
struct sockaddr_in target_pc, me;
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
target_pc.sin_family = PF_INET;
target_pc.sin_port = htons(PORT);
me.sin_family = PF_INET;
me.sin_port = htons(0);
me.sin_addr.s_addr = htonl(INADDR_ANY);
i = bind(sock, (struct sockaddr *) &me, sizeof(me));
if( i < 0)
{
printf("bind result: %d\n", i);
return -1;
}
nbytes = 200;
char str_addr[] = "155.55.25.25";
target_pc.sin_addr.s_addr = inet_addr(&str_addr[0]);
while(1)
{
nbytes = strlen(buffer);
flags = 0;
sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc));
int addrlen = sizeof(target_pc);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen);
if((size > 0) && (size < 200))
{
buffer[size] = '\0';
i = puts((char *) buffer);
}
printf("%i --- Size: %lu\n", a, sizeof(buffer));
a = a + 1;
}
return 0;
}
Below my Server Code:
/*** SERVER ***/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 20009
void SleepMs(int ms)
{
usleep(ms*1000); //convert to microseconds
return;
}
int main()
{
int sock;
int size;
int nbytes, flags;
socklen_t addrlen;
int i;
char buffer[100];
char buffer2[] = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\0";
struct sockaddr_in server;
struct sockaddr_in from;
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(PORT);
i = bind(sock, (struct sockaddr *) &server, sizeof(server));
if( i < 0){
printf("bind result: %d\n", i);
return -1;
}
else{
printf("Simple UDP server is ready!\n");
}
nbytes = 200;
flags = 0;
while(1)
{
addrlen = sizeof(from);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen);
if((size > 0) && (size < 200))
{
buffer[size] = '\0';
i = puts((char *) buffer);
}
printf("\n");
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
sendto(sock, buffer2, nbytes, flags, (struct sockaddr *)&from,addrlen);
SleepMs(10); // Packet-to-Packet Delay Time
}
return 0;
}
You can have the connection using IP of the server in this case 192.168.1.2
server.sin_addr.s_addr = inet_addr("192.168.1.2");
using this in both codes

udp socket - bind and connect succeed but send does not work [closed]

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'm trying to communicate through a connected-udp-socket between two peer's. The address information between the peers is transmitted via a server using tcp.
First each peer set's up an udp-socket, binds an address and then transmit the address information via tcp to a server. The server sends the connection information to the other peer.
When the peer receives the information it tries to 'connect' the udp-socket to the other peer. The connect call succeed, but send gives me the following error: 'errno: 89, Destination address required'.
peer.c:
#include "Socket.h"
#include "function.h"
int main (int argc, char** argv) {
if(argc != 4) {
printf("3 Parameter must be given.\nclient-ip server-ip server-port\n");
exit(-1);
}
struct sockaddr_in my_addr, server_addr, other_peer_addr;
address_info* msg_address_info;
header *msg;
int recv_done = 0;
int optval = 1;
int fd_udp, fd_server;
ssize_t len;
socklen_t my_addr_len;
fd_set rfds;
FD_ZERO(&rfds);
fd_udp = Socket(AF_INET, SOCK_DGRAM, 0);
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
my_addr.sin_len = sizeof(struct sockaddr_in);
#endif
my_addr.sin_port = 0; // any port
if ((my_addr.sin_addr.s_addr = (in_addr_t)inet_addr(argv[1])) == INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Bind(fd_udp, (const struct sockaddr *) &my_addr, sizeof(my_addr));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int));
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr_len = sizeof(my_addr);
//get the current address for server registration
Getsockname(fd_udp, (struct sockaddr *) &my_addr, &my_addr_len);
/* TCP Communication */
/* i use 127.0.0.1:55555 for the server */
fd_server = Socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
server_addr.sin_len = sizeof(struct sockaddr_in);
#endif
server_addr.sin_port = htons(atoi(argv[3]));
if ((server_addr.sin_addr.s_addr = (in_addr_t) inet_addr(argv[2]))
== INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Connect(fd_server, (const struct sockaddr *) &server_addr, sizeof(server_addr));
len = sizeof(address_info);
msg_address_info = malloc(len + get_padding(len));
memset((void*)msg_address_info, 0, len + get_padding(len));
msg_address_info->head.type = htons(30);
msg_address_info->head.length = htons(sizeof(address_info));
msg_address_info->ip = my_addr.sin_addr.s_addr;
msg_address_info->port = my_addr.sin_port;
Send(fd_server, msg_address_info, len + get_padding(len), 0);
free(msg_address_info);
while(!recv_done) {
FD_ZERO(&rfds);
FD_SET(fd_server, &rfds);
//data is ready for recv
if(FD_ISSET(fd_server, &rfds)) {
msg = recv_stream(fd_server);
if(msg != NULL) {
if(ntohs(msg->type) == 3) {
Close(fd_server);
recv_done = 1;
msg_address_info = (address_info *) msg;
other_peer_addr.sin_addr.s_addr = msg_address_info->ip;
other_peer_addr.sin_port = msg_address_info->port;
}
}
}
}
char buf[512];
memset((void*)&buf, 0, 512);
char* other_peer_ip;
int other_peer_port;
other_peer_ip = inet_ntoa(other_peer_addr.sin_addr);
other_peer_port = ntohs(other_peer_addr.sin_port);
printf("other_peer ip: %s\nother_peer port: %i\n", other_peer_ip, other_peer_port); //matches on bothe peer's
int ret_con = connect(fd_udp, (const struct sockaddr *) &other_peer_addr, sizeof(other_peer_addr));
fprintf(stderr, "ret_con: %i, errno: %i, %s\n", ret_con, errno, strerror(errno));
int ret_send = send(fd_udp, buf, 512, 0);
if(ret_send < 0) {
fprintf(stderr, "ret_send: %i, errno: %i, %s\n", ret_send, errno, strerror(errno));
}
}
function.h:
#define BUFFER_SIZE (1<<16)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <err.h>
#include <netdb.h>
#include <errno.h>
#include "Socket.h"
typedef struct {
uint16_t type;
uint16_t length;
} header;
typedef struct {
header head;
uint32_t ip;
uint16_t port;
} address_info;
int get_padding(int length);
void* recv_stream(int fd);
functions.c:
#include "functions.h"
void* recv_stream(int fd) {
if(fd < 0) {
fprintf(stderr, "recv_stream: Invaild fd\n");
return NULL;
}
ssize_t len;
int msg_length;
char buf[BUFFER_SIZE];
char* msg;
len = recv(fd, &buf, BUFFER_SIZE, MSG_PEEK);
//Client has closed the connection
if(len <= 0) {
fprintf(stderr, "recv_stream: Client closed the connection.\n");
exit(-1);
}
#ifdef DEBUG
printf("PEEKED %zd bytes.\n", len);
#endif
if(len < sizeof(header)) {
fprintf(stderr, "recv_stream: Message to small no header\n");
return NULL;
}
header *head = (header *) buf;
msg_length = ntohs(head->length);
if(len < msg_length) {
fprintf(stderr, "recv_stream: Message to small\n");
return NULL;
}
else if(len >= msg_length + get_padding(msg_length)) {
msg = malloc(msg_length + get_padding(msg_length));
len = Recv(fd, msg, msg_length + get_padding(msg_length), 0);
head = (header *) msg;
}
return head;
}
int get_padding(int length) {
if(length <= 0) {
fprintf(stderr, "get_padding: wrong length");
}
int pad = length % 4;
if(pad == 3)
pad = 1;
else if(pad == 1)
pad = 3;
return pad;
}
Socket.c with Wrapper functions
int Socket(int fd, int type, int protocol) {
int n;
if((n=socket(fd,type,protocol)) < 0) {
perror("socket");
exit(-1);
}
return n;
}
/* many more */
I read already following question Can you bind() and connect() both ends of a UDP connection but it did not solve my problem.
The transfer of the address information seems to be correct. I printed the send and received addresses on both peers and they match.
I'm stucked on this problem and can't figure out my mistake. Can you help me?
Edit:
provided new example
Now i get the following error:
ret_con: -1, errno: 97, Address family not supported by protocol
ret_send: -1, errno: 89, Destination address required
You are not populating the sin_family field of other_peer_addr before calling connect() on the UDP socket. You are only populating the sin_addr and sin_port fields, which is not enough. connect() needs to be told the type of address being passed to it and that must use the same family as the socket (just like with bind()). Since you are not populating the sin_family field, it contains a random value from the stack, and that is causing connect() to fail with the "Address family not supported" error, and send() cannot be called on an unconnected socket, thus causing the "Destination address required" error.

connect() function taking too long

When I type in to the terminal:
echo "GET /" | ./<executable name> www.google.com <port number, usually 80>
the terminal just sits there like it's waiting for input or it's stuck in an infinite loop. What is happening is that connection is taking too long I think.
/*Creating socket*/
int sock = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("error creating socket\n");
exit(1);
}
printf("1\n");
/*Establish connection to the echo server*/
int r = connect(sock, addrList->ai_addr, addrList->ai_addrlen);
printf("1.5\n");
if (r < 0) {
perror("Connection failed\n");
exit(1);
}
printf("2\n");
Here, the 1 prints out, but the 1.5 right after the connect doesn't print out and the terminal just sits.
This problem didn't happen before and I used to get the page's source code back instantly. But now this problem is occurring.
It started occurring after I typed in to the terminal: netstat -an -A inet | grep :2525
so this may have had an effect.
Here is the entire 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>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid arguments\n");
exit(1);
}
char *serverIP = argv[1]; /*Server hostname*/
char *portNumber = argv[2]; /*Port Number*/
void *numericAddress;
char addrBuffer[INET6_ADDRSTRLEN];
in_port_t port;
char buffer_stdin[65535];
char buffer_stdout[65535];
int bytes_read = 0;
int bytes_written = 0;
/*getting integral number of string representation of port number*/
in_port_t servPort = atoi(argv[2]);
/*------------------get binary number of hostname-----------------*/
struct addrinfo addrCriteria;
memset(&addrCriteria, 0, sizeof(addrCriteria));
addrCriteria.ai_family = AF_INET;
addrCriteria.ai_socktype = SOCK_STREAM;
addrCriteria.ai_protocol = IPPROTO_TCP;
struct addrinfo *addrList;
int rtnVal = getaddrinfo(serverIP, portNumber, &addrCriteria, &addrList);
if (rtnVal != 0) {
printf("getaddrinfo() failed\n");
exit(1);
}
numericAddress = &((struct sockaddr_in *) (addrList->ai_addr))->sin_addr;
/*Converting port to binary*/
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htonl(servPort);
/*----------------------------------------------------------------*/
inet_ntop(addrList->ai_addr->sa_family, numericAddress, addrBuffer, sizeof(addrBuffer));
printf("IP ADDRESS: %s\n", addrBuffer);
/*Creating socket*/
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("error creating socket\n");
exit(1);
}
/*printf("1\n");*/
/*Establish connection to the echo server*/
int r = connect(sock, addrList->ai_addr, addrList->ai_addrlen);
printf("%d\n", r);
if (r < 0) {
perror("Connection failed\n");
exit(1);
}
printf("2\n");
/*Reading from stdin and writing to socket until stdin ends
bytes_read = read(0, buffer_stdin, sizeof(buffer_stdin));
write(sock, buffer_stdin, bytes_read);*/
while ((bytes_read = read(0, buffer_stdin, sizeof(buffer_stdin)-1)) > 0) {
write(sock, buffer_stdin, bytes_read);
}
/*Shutting down write end of socket*/
int r_shutdown = shutdown(sock, SHUT_WR);
if (r_shutdown < 0) {
printf("Shutting down write end of socket failed\n");
exit(1);
}
/*Reading from socket and writing to stdout until socket ends*/
while ((bytes_read = read(sock, buffer_stdout, sizeof(buffer_stdout)-1)) > 0) {
write(1, buffer_stdout, bytes_read);
}
close(sock);
exit(0);
}
The correct way to do it is :
struct sockaddr_in address;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd!=-1)
{
perror("socket :");
printf("sockfd = %d\n", sockfd);
}
else
{
perror("socket");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(9734);
len = sizeof(struct sockaddr_in);
result = connect(sockfd, (struct sockaddr *)&address, len);
Nvm I figured it out.
Apparently I had to take into account big endian vs little endian, and so in this line:
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htonl(servPort);
the htonl should've been htons, so:
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htons(servPort);

Connection refused implementing a tcp server

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)

Resources