a random port is chosen while initing socket [closed] - c

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);
}

Related

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

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);

Strange behaviour while sending broadcast message

I have two programs: client and server. They're trying to find themselves in local network using broadcast.
Client sends simple packet on broadcast with SERVER_PORT (known before) and server prints info about connection, but when i tried this solution I found some strange behavaiour, when I uncomment last two lines of server.c server prints (one custom struct)
Connection from: 0.0.0.0 on port: 0
after commenting those lines everything works properly, am I missing something?
server.c
int broadcast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in broadcast_addr;
broadcast_addr.sin_addr.s_addr = INADDR_ANY;
broadcast_addr.sin_port = htons(SERVER_PORT);
broadcast_addr.sin_family = AF_INET;
if (bind(broadcast_socket, (struct sockaddr *)&broadcast_addr,
sizeof(broadcast_addr))) {
perror("bind");
}
struct sockaddr_in recv_addr;
char buf[MAX_PACKET_SIZE];
socklen_t len;
if (recvfrom(broadcast_socket, buf, MAX_PACKET_SIZE, 0,
(struct sockaddr *)&recv_addr, &len) < 0) {
perror("recvfrom");
}
printf("Connection from: %s on port: %d\nMessage: %s\n",
inet_ntoa(recv_addr.sin_addr), ntohs(recv_addr.sin_port), buf);
/* struct network_packet packet; */
/* struct sockaddr_in my_addr; */
client.c
int find_server(struct sockaddr_in *out) {
struct sockaddr_in broadcast;
struct network_packet packet;
int yes = 1;
socklen_t len;
broadcast.sin_addr.s_addr = INADDR_ANY;
broadcast.sin_port = htons(CLIENT_PORT);
broadcast.sin_family = AF_INET;
int socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (bind(socket_fd, (struct sockaddr *)&broadcast, sizeof(broadcast))) {
perror("bind");
}
if (get_broadcast_addr(&broadcast.sin_addr)) {
return -1;
}
printf("Target address: %s\n", inet_ntoa(broadcast.sin_addr));
broadcast.sin_port = htons(SERVER_PORT);
broadcast.sin_family = AF_INET;
setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
char buf[10] = "test";
sendto(socket_fd, buf, strlen(buf), 0, (struct sockaddr *)&broadcast,
sizeof(broadcast));
if (recvfrom(socket_fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&broadcast, &len) < 0) {
perror("recvfrom");
}
struct sockaddr_in *sa = (struct sockaddr_in *)packet.data;
memcpy(out, sa, packet.header.packet_length);
return 0;
}
struct network_packet_header {
enum network_packet_type type;
int packet_length;
};
struct network_packet {
struct network_packet_header header;
unsigned char data[MAX_DATA_LENGTH];
};
You have to initialize the variable you pass as recvfrom's addrlen to the size of the address struct.

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.

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