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;
}
Related
I am trying to send data from my client to server, but my server isn't receiving the message, I am not sure why. The client receives Connected message and it's displaying. How can I get the server to receive messages from client? Also, should I use close() function in the server for loop?
Client
int main(){
char server_response[256];
char send_msg[256] = "Sending to server";
int server;
server = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(9002);
address.sin_addr.s_addr=INADDR_ANY;
int con = connect(server,(struct sockaddr*) &address, sizeof(address));
if(con == -1) {
printf("Error with connection");
return -1;
}
recv(server, server_response, sizeof(server_response), 0);
int toServer = send(server, send_msg, sizeof(send_msg), 0);
if(toServer == -1) {
perror();
}
printf("%s", server_response);
return 0;
}
Server
int main(){
char server_response[256] = "Connected";
int server;
char from_client[256];
server = socket(AF_INET, SOCK_STREAM, 0);
if(server == -1) {
perror();
return -1;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(9002);
address.sin_addr.s_addr=INADDR_ANY;
int bindx = bind(server,(struct sockaddr*) &address, sizeof(address));
if(bindx == -1) {
perror();
return -1;
}
listen(server, 5);
for(;;) {
int client_socket = accept(server, NULL, NULL);
send(client_socket, server_response, sizeof(server_response), 0);
recv(client_socket, from_client, sizeof(from_client), 0);
printf("%s", from_client);
}
return 0;
}
It seems you have some synchronization problem. That is either server and client both are in send mode or both in recv mode. It's better to follow a request-response pattern which means server be in listening mode after accept the client. So change the server code to recv/printf/send pattern and client to send/receive mode or just send mode.
Server:
int main(){
char server_response[256] = "Connected";
int server;
char from_client[256];
server = socket(AF_INET, SOCK_STREAM, 0);
if(server == -1) {
perror();
return -1;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(9002);
address.sin_addr.s_addr=INADDR_ANY;
int bindx = bind(server,(struct sockaddr*) &address, sizeof(address));
if(bindx == -1) {
perror();
return -1;
}
listen(server, 5);
for(;;) {
int client_socket = accept(server, NULL, NULL);
recv(client_socket, from_client, sizeof(from_client), 0);
printf("%s", from_client);
send(client_socket, server_response, sizeof(server_response), 0);
}
return 0;
}
Client:
int main(){
char server_response[256];
char send_msg[256] = "Sending to server";
int server;
server = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(9002);
address.sin_addr.s_addr=INADDR_ANY;
int con = connect(server,(struct sockaddr*) &address, sizeof(address));
if(con == -1) {
printf("Error with connection");
return -1;
}
int toServer = send(server, send_msg, sizeof(send_msg), 0);
if(toServer == -1) {
perror();
}
recv(server, server_response, sizeof(server_response), 0);
printf("%s", server_response);
return 0;
}
And stare server before client. See online demo provided.
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.
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.
I'm trying to make a program that uses sockets between a client and a server. In my code below if I comment on the loop while my server receives my message but if I do not comment my client seems not to send my message (finally my server never receives my message). Why ?
Server
int main()
{
message = malloc(sizeof(char));
printf("Waiting for incoming connections ...\n");
sem_init(&lock, 0, 1);
// socket creation
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// dserver address9002
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind the socket to IP and port
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, MAX_CONNECTIONS);
int client_socket;
int i = 0;
while(client_counter < 2 && (client_socket = accept(server_socket, NULL,NULL)))
{
client_counter++;
client_sockets[i] = client_socket;
i++;
printf("new client ! \n");
}
//here i create a thread for each client and in this thread there is a while loop with a recv function
}
Client
int socket_connection(char* ip, int port)
{
int network_socket = 0;
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = inet_addr(ip);
if ((network_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address));
if (connection_status < 0)
{
printf("Error while creating / connecting the socket");
return -1;
}
return network_socket;
}
void connect_to_server()
{
char ip[256];
int port;
strcpy(ip, "127.0.0.1");
port = 9002;
// try to connect to the server with the IP and port
int network_socket = socket_connection(ip, port);
char server_reponse[256];
char message[256];
// clean string
memset(server_reponse, 0, sizeof(server_reponse));
recv(network_socket, &server_reponse, sizeof(server_reponse), 0);
if (strcmp(server_reponse, "instruction: make board") == 0)
{
construct_game_board();
show_game_board();
memset(message, 0, sizeof(message));
put_ship(message);
printf("Finish to make board\n");
}
printf("Reponse send to socket %d: %zu\n",network_socket, send(network_socket, message, strlen(message), 0));
while (1) {
printf("Before recv\n");
printf("Reponse recv : %zu\n", recv(network_socket, server_reponse, sizeof(server_reponse), 0));
printf("After recv\n");
}
In my console when i launch i have : Reponse send to socket 3: 0 and Before recv