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
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);
}
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.
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?
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;
}
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");
}
}
}