sendto() for UDP server is not sending data to client - c

I'm lost, but the title sums it up. I'm trying to make a UDP server using netster, but for whatever reason, I'll get data from the client but not the other way around. I suspect it has something to do with clientaddr due to getting an error "sendto: Address family not supported by protocol," but I've looked over multiple examples and this seemed like the documented way to use the struct.
I really cannot pinpoint the issue here so I'll show all my code
void chat_server(char* iface, long port, int use_udp)
{
struct addrinfo hints;
struct addrinfo *results, *rp;
char buff4[INET_ADDRSTRLEN];
void* raw_addr;
int sfd = 0, valread, connectfd;
short end = 0;
char cport[7];
struct sockaddr_in servaddr, clientaddr;
socklen_t addrlen;
char* rescbuff;
sprintf(cport, "%ld", port);
size_t count = 0;
//TCP & UDP FLAGS
if(use_udp)
{
hints.ai_protocol = IPPROTO_UDP;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
}
else
{
hints.ai_protocol = IPPROTO_TCP;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
}
hints.ai_flags = AI_PASSIVE;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
//get IP address and socket from server
if(getaddrinfo(iface, cport, &hints, &results))
{
perror("getaddrinfo");
exit(-1);
}
for(rp = results; rp != NULL; rp = rp->ai_next)
{
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(sfd == -1) continue;
if(rp->ai_family == AF_INET)//(results->ai_family == AF_INET)
{
struct sockaddr_in* tmp = (struct sockaddr_in*)rp->ai_addr;
raw_addr = &(tmp->sin_addr);
inet_ntop(AF_INET, raw_addr, buff4, INET_ADDRSTRLEN);
break;
}
}
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
//bind
valread = bind(sfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
if(valread == -1)
if(valread == -1)
{
perror("bind server");
exit(-1);
}
addrlen = sizeof(clientaddr);
rescbuff = malloc(MAX_S*sizeof(char*));
do
{
//get client IP + count connections starting at 0
//memset(&clientaddr, 0, sizeof(clientaddr));
struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&clientaddr;
struct in_addr ipAddr = pV4Addr->sin_addr;
char str[INET_ADDRSTRLEN];
inet_ntop( AF_INET, &ipAddr, str, INET_ADDRSTRLEN );
clientaddr.sin_family = AF_INET;
//clientaddr.sin_addr.s_addr = inet_addr(str);
do //communicate loop
{
socklen_t len;
memset(rescbuff, 0, MAX_S);
valread = 0;
//get message
valread = recvfrom(sfd, rescbuff, MAX_S, 0, (struct sockaddr*)&clientaddr, &len);
if( valread == -1)
{
perror("recvfrom");
exit(-1);
}
//acknowledge
printf("got message from('%s', %d)\n",str, servaddr.sin_port);
printf("message %s\n", rescbuff);
//reply to message
printf("try1\n");
//valread = sendto(sfd, rescbuff, strlen(rescbuff), 0, ( struct sockaddr*)&clientaddr, sizeof(clientaddr));
valread = sendto(sfd, "hello\n", 20, 0, (struct sockaddr*)&clientaddr, sizeof(clientaddr));
if(valread == -1)
{
perror("sendto");
exit(-1);
}
printf("bytes sent: %d\n", valread);
}
while(1);
if(end) break;
}
while(1);
close(sfd);

Related

a random port is chosen while initing socket [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 2 years ago.
Improve this question
int create_socket(struct in_addr *ip, unsigned int port) {
int s = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = (port);
sin.sin_addr.s_addr = ip;
connect(s, &sin, sizeof(sin));
return s;
}
I try to create socket to connect to of my server, and whenever I run this code the process tries to connect to a random socket.
the function is called with the following parameters:
inet_aton(argv[1], &ip); //argv[1]=='127.0.0.1'
unsigned int port = htons(atoi(argv[2])); //argv[2]=='8080'
Anyone detects the mistake?
The problem was with this:
int create_socket(struct in_addr *ip, unsigned int port) {
int s = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = (port);
sin.sin_addr.s_addr =ip->s_addr; // this is where the problem was
err_handler(connect(s, (struct sockaddr *)&sin, sizeof(sin)));
return s;
}
Try something more like this:
int create_socket(struct in_addr *ip, unsigned short port) {
int s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) return -1;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = ip->s_addr;
if (connect(s, &sin, sizeof(sin)) < 0) {
close(s);
s = -1;
}
return s;
}
struct in_addr ip;
inet_aton(argv[1], &ip); //argv[1]=="127.0.0.1"
unsigned short port = atoi(argv[2]); //argv[2]=="8080"
int sckt = create_socket(&ip, port);
if (sckt < 0) {
...
}
else {
...
close(sckt);
}
A better option is to use getaddrinfo() instead, let it do all the parsing and setup of the sockaddr_in for you:
int create_socket(const char *ip, const char *port) {
struct addrinfo hints, *addrs, *addr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int res = getaddrinfo(ip, port, &hints, &addrs);
if (res < 0) {
return -1;
}
for(addr = addrs; addr != NULL; addr = addr->ai_next) {
int s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (s < 0) continue;
if (connect(s, addr->ai_addr, addr->ai_addrlen) == 0) {
freeaddrinfo(addrs);
return s;
}
close(s);
}
freeaddrinfo(addrs);
return -1;
}
int sckt = create_socket(argv[1], argv[2]);
if (sckt < 0) {
...
}
else {
...
close(sckt);
}

Did my code cause too many socket didn't get release

I wrote a network ICMP ping code in C, the following is my code, it tried to ping thousands of IP, but after a few days run, the total number of open socket increased to 35K. Where should I release my socket please.
struct packet {
struct icmphdr hdr;
char msg[64 - sizeof(struct icmphdr)];
};
struct protoent *proto = NULL;
void ping(char *bindIp, char **ipArr, size_t ipCount) {
//bindIp is the Ip in my machine for sending ip
//ipArr is the destination Ips need to ping
//ipCount is the total destination ip number
const int val = 255;
int i, sd, cnt = 1;
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_addr.s_addr = inet_addr(bindIp);
r_addr.sin_port = 0;
sd = socket(PF_INET, SOCK_RAW, proto->p_proto);
bind(sd, (struct sockaddr *) &r_addr, sizeof(r_addr));
if (sd < 0) {
perror("socket,you might need root/admin to operate\n");
return;
}
if (setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
perror("Set TTL option");
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
perror("Request nonblocking I/O");
for (i = 0; i < ipCount; i++) {
struct packet pckt;
struct hostent *hname;
hname = gethostbyname(ipArr[i]);
struct sockaddr_in addr;
proto = getprotobyname("ICMP");
bzero(&addr, sizeof(addr));
addr.sin_port = 0;
addr.sin_family = hname->h_addrtype;
addr.sin_addr.s_addr = *(long*) hname->h_addr;
if(i%5==0){
usleep(1001);
if(i%50000==0){
printf("ping oversea--i=%d,ip=%s\n",i,ipArr[i]);
}
}
bzero(&pckt, sizeof(pckt));
pckt.hdr.type = ICMP_ECHO;
long currTs = current_timestamp();
char buffer[20];
sprintf(buffer,"_%lu", currTs);
char *payload=concat(sendIp,buffer);
strcpy(pckt.msg,payload);
pckt.hdr.un.echo.id = 8899;
pckt.hdr.un.echo.sequence = cnt++;
pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
free(payload);
sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*) &addr,
sizeof(addr));
}
}
You should close the socket at the end of the function. After the for loop.

UDP bad length for IPv6 raw socket

My program should sending UDP datagrams, using Raw socket for IPv6 protocol.
I have to use IPV6 CHECKSUM in socket options. Code is compiled well, but TCPDump is showing bad length.
IP6 fe80::20c:29ff:fe95:c051.24576 > waw02s13-in-x03.1e100.net.0: UDP, bad length 12280 > 40
What I miss or what i'm doing wrong?
int main(int argc, char** argv) {
int sockfd;
int offset;
int retval;
struct addrinfo hints;
struct addrinfo *rp, *result;
unsigned char datagram[sizeof(struct ip6_hdr) + sizeof(struct udphdr)
] = {0};
struct ip6_hdr *ip_header = (struct ip6_hdr *)datagram;
struct udphdr *udp_header = (struct udphdr *)
(datagram + sizeof(struct ip6_hdr));
if (argc != 3) {
fprintf(
stderr,
"Invocation: %s <HOSTNAME OR IP ADDRESS> <PORT>\n",
argv[0]
);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_UDP;
retval = getaddrinfo(argv[1], NULL, &hints, &result);
if (retval != 0) {
fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
offset = 6;
for (rp = result; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd == -1) {
perror("socket()");
continue;
}
retval = setsockopt(
sockfd,
IPPROTO_IPV6, IPV6_CHECKSUM,
&offset, sizeof(offset)
);
if (retval == -1) {
perror("setsockopt()");
exit(EXIT_FAILURE);
} else {
break;
}
}
if (rp == NULL) {
fprintf(stderr, "Client failure: could not create socket.\n");
exit(EXIT_FAILURE);
}
ip_header->ip6_flow = htonl((6 << 28) | (0 << 20) | 0);
ip_header->ip6_hops = 255;
ip_header->ip6_nxt = IPPROTO_UDP;
ip_header->ip6_plen = sizeof(struct ip6_hdr)
+ sizeof(struct udphdr);
inet_pton(AF_INET6, SOURCE_ADDRESS, &(ip_header->ip6_src));
inet_pton(AF_INET6, argv[1], &(ip_header->ip6_dst));
udp_header->uh_sport = htons(SOURCE_PORT);
udp_header->uh_dport = htons(atoi(argv[2]));
udp_header->uh_ulen = htons(ip_header->ip6_plen);
fprintf(stdout, "Sending UDP...\n");
for (;;) {
retval = sendto(
sockfd,
datagram, ip_header->ip6_plen,
0,
rp->ai_addr, rp->ai_addrlen
);
if (retval == -1) {
perror("sendto()");
}
sleep(1);
}
exit(EXIT_SUCCESS);
}
Wireshark Image
Any ideas?

Can UDP multicast sucess while offline?

a demo about UDP multicast,when i want to test if the code is right, I found failed ,but i think is not the problem of the code.My virtual machine is offline,so i think whether is udp cannot multicast when the machine is offline?
this is my code:
//this is for receive
int main(int argc,char **argv) //My Multicast address is 224.0.0.88
{
int udpsocket;
int res;
char buf[50];
struct sockaddr_in saddr;
struct sockaddr_in raddr;
bzero(&saddr,sizeof(saddr));
bzero(&raddr,sizeof(raddr));
// 初始化地址结构体变量
saddr.sin_family = AF_INET;
saddr.sin_port = htons(5001);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
// 定义并初始化组播的结构体
struct ip_mreq mreq;
bzero(&mreq, sizeof mreq);
mreq.imr_multiaddr.s_addr = inet_addr(argv[1]); //组播地址,D类型
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
// 创建udp套接字
udpsocket = socket(AF_INET,SOCK_DGRAM,0);
if(udpsocket == -1)
{
perror("create udp socket failed!\n");
return -1;
}
// 设置可以组播
setsockopt(udpsocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof mreq);
int ret = sizeof(struct sockaddr);
// 绑定
res = bind(udpsocket,(struct sockaddr *)&saddr,ret);
if(res == -1)
{
perror("bind udp socket failed!\n");
return -1;
}
while(1)
{
puts("111");
bzero(buf,50);
recvfrom(udpsocket,buf,50,0,(struct sockaddr *)&raddr,&ret);
printf("message recv from %s\n",buf);
}
close(udpsocket);
return 0;
}
//this is for send message
int main(int argc,char **argv)
{
int udpsocket;
int res;
char buf[50];
struct sockaddr_in saddr;
bzero(&saddr,sizeof(saddr));
// 初始化地址结构体变量
saddr.sin_family = AF_INET;
saddr.sin_port = htons(5001);
saddr.sin_addr.s_addr = inet_addr(argv[1]);
// 创建udp套接字
udpsocket = socket(AF_INET,SOCK_DGRAM,0);
if(udpsocket == -1)
{
perror("create udp socket failed!\n");
return -1;
}
// 将套接字的属性设置为可以广播
int on = 1;
setsockopt(udpsocket, SOL_SOCKET, SO_BROADCAST, &on, sizeof on);
setsockopt(udpsocket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on);
int ret = sizeof(struct sockaddr);
while(1)
{
bzero(buf,50);
printf("please input a message !\n");
scanf("%s",buf);
sendto(udpsocket,buf,50,0,(struct sockaddr *)&saddr,ret);
}
close(udpsocket);
return 0;
}

Send url patterns to C sockets retrieve it

I'm trying to build an application that can behave like a real server which can connect multiple clients and dispatch the path to respond to different urls.
Can we send a url like
127.0.0.1:32000/urlPath/OtherSubPath
to a server socket build using socket(PF_INET, SOCK_STREAM, 0)? And get the url string at the server side? My server socket code looks like this.
sockfd = socket(PF_INET, SOCK_STREAM, 0);
servaddr.sin_family = PF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(32000);
Below is a part of the code.
int sockfd, n;
struct sockaddr_in servaddr, cliaddr;
socklen_t len;
char mesg[1000];
servaddr.sin_family = PF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // htonl(INADDR_ANY); //inet_addr("127.0.0.1");
servaddr.sin_port = htons(32000);
if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof (servaddr)) == -1)
error("Can't bind the port");
len = sizeof (cliaddr);
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("Current local time and date: %s", asctime(timeinfo));
// printf("IP %s\n", servaddr.sin_addr.s_addr);
char* banner = "Hello UDP client! This is UDP server";
struct timeval stop, start;
pthread_t t0;
if (pthread_create(&t0, NULL, request_balancer, NULL) == -1) {
printf("Error in pthread for request balance");
}
if (listen(sockfd, 10) == -1)
error("Can't listen");
while (1) {
struct sockaddr_storage client_addr;
unsigned int address_size = sizeof (client_addr);
int connect_d = accept(sockfd, (struct sockaddr *) &client_addr, &address_size);
if (connect_d == -1) {
printf("Cannot open a socket");
break;
}
web_req_count++;
n = recvfrom(connect_d, mesg, 1000, 0, (struct
sockaddr*) &cliaddr, &len);
printf("Recieved: %d\n", web_req_count);
int pid = fork();
if (pid == 0) {
while (1) {
banner = asctime(timeinfo);
time(&rawtime);
timeinfo = localtime(&rawtime);
sleep(1);
send(connect_d, banner, strlen(banner), 0);
int line_cnt = 0;
printf("Recieved \n");
}
}
}

Resources