向所有客户端发送套接字udp c

时间:2016-04-10 22:36:11

标签: c sockets udp

我想向我的udp服务器中连接的所有客户端发送来自一个客户端的消息,我有这样的错误:协议不支持的地址族。 所以我在网上寻找解决方案,但我什么都没看到。如果你能帮助我纠正这个错误,我会很高兴,

此致

/* 
 * UDP server
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUFSIZE 1024

/*
 * write error
 */
void error(char *msg) {
  perror(msg);
  exit(1);
}

int main(int argc, char **argv) {
  int sockfd; /* socket */
  int portno; 
  int clientlen; 
  struct sockaddr_in serveraddr; 
  struct sockaddr_in *clientaddr;
  struct hostent *hostp;
  char buf[BUFSIZE]; 
  char *hostaddrp; 
  int optval; 
  int n; 
  int i=0;

  if (argc != 2) {
    fprintf(stderr, "missing arguments.", argv[0]);
    exit(1);
  }
  portno = atoi(argv[1]);


  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sockfd < 0) 
    error("error socket");

  optval = 1;
  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 
         (const void *)&optval , sizeof(int));

  /*
   * create address server 
   */
  bzero((char *) &serveraddr, sizeof(serveraddr));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  serveraddr.sin_port = htons(8080);


  if (bind(sockfd, (struct sockaddr *) &serveraddr, 
       sizeof(serveraddr)) < 0) 
    error("error whie associating bind and socket");


  clientlen = sizeof(*clientaddr);
  while (1) {

    clientaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
    hostp = (struct hostent *)malloc(sizeof(struct hostent));
    int length = sizeof(*clientaddr) / sizeof(clientaddr[0]);
    bzero(buf, BUFSIZE);
    n = recvfrom(sockfd, buf, BUFSIZE, 0,
          (struct sockaddr *) &clientaddr[i], &clientlen);

    if (n < 0)
      error("error recvfrom");


    hostp = gethostbyaddr((const char *)&clientaddr[i].sin_addr.s_addr, 
              sizeof(clientaddr[0].sin_addr.s_addr), AF_INET);
    if (hostp == NULL)
      error("error gethostbyaddr");
    hostaddrp = inet_ntoa(clientaddr[i].sin_addr);
    if (hostaddrp == NULL)
      error("error inet_ntoa\n");
    printf("server received datagram from: %s (%s)\n", 
       hostp->h_name, hostaddrp);
    printf("server received %d/%d octets: %s\n", strlen(buf), n, buf);


     int k =0;
     for(k;k<length;k++){
          n = sendto(sockfd, buf, strlen(buf), 0, 
           (struct sockaddr *) &clientaddr[k], clientlen);
            if (n < 0) 
              error("error sendto");    
     }
    i++;          
  }
  close(sockfd);

}

编辑:我最新的udp服务器和java客户端(ihmgui):

/* 
 * Serveur en UDP
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUFSIZE 1024
#define MAX_CLIENTS 1000

/*
 * écrire une erreur
 */
void error(char *msg) {
  perror(msg);
  exit(1);
}

int main(int argc, char **argv) {
  int sockfd; /* socket */
  int portno; /* port à écouter */
  int clientlen; /* taille de l'adresse ip du client */
  struct sockaddr_in serveraddr; /* adresse serveur */
  struct sockaddr_in *clientaddr[MAX_CLIENTS]; /* adresse client */
  struct hostent *hostp; /* info de l'hôte client */
  char buf[BUFSIZE]; /* message du buffer */
  char *hostaddrp; /* pour lire les points de l'adresse ip */
  int optval; /* valeur pour setsockopt */
  int n; /* taille du message en octet*/
  int i=0;
  int length = 0;
  /* 
   * on vérifie si l'utilisateur à bien définit un port en parametre
   */
  if (argc != 2) {
    fprintf(stderr, "vous avez oublier de mettre un port en argument.", argv[0]);
    exit(1);
  }
  portno = atoi(argv[1]);

  /* 
   * socket: créer un socket parent
   */
  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sockfd < 0) 
    error("erreur lors de l'ouverture de la socket");

  optval = 1;
  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 
         (const void *)&optval , sizeof(int));

  /*
   * créer l'adresse internet du serveur
   */
  bzero((char *) &serveraddr, sizeof(serveraddr));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  serveraddr.sin_port = htons(8080);

  /* 
   * bind: associe les sockets parents au port défini
   */
  if (bind(sockfd, (struct sockaddr *) &serveraddr, 
       sizeof(serveraddr)) < 0) 
    error("erreur lors de l'association des sockets et du port");

  /* 
   * boucle principale qui attend les datagram socket
   */
  while (1) {
      clientlen = sizeof(struct sockaddr_in); 
    /*
     * recvfrom: reçoit un datagrame de type UDP d'un client
     */
    clientaddr[i] = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
    hostp = (struct hostent *)malloc(sizeof(struct hostent));
    bzero(buf, BUFSIZE);
    n = recvfrom(sockfd, buf, BUFSIZE, 0,
            (struct sockaddr*)clientaddr, &clientlen);

    if (n < 0)
      error("erreur dans le recvfrom");

    /* 
     * gethostbyaddr: determine qui a envoyé le message
     */
    hostp = gethostbyaddr((const char *)&clientaddr[i]->sin_addr.s_addr, 
              sizeof(clientaddr[i]->sin_addr.s_addr), AF_INET);
    if (hostp == NULL)
      error("erreur sur gethostbyaddr");
    hostaddrp = inet_ntoa(clientaddr[i]->sin_addr);
    if (hostaddrp == NULL)
      error("erreur sur inet_ntoa\n");
    printf("le serveur a recu un datagram de: %s (%s)\n", 
       hostp->h_name, hostaddrp);
    printf("le serveur a recu %d/%d octets: %s\n", strlen(buf), n, buf);

    /* 
     * sendto: réecrit à tout les clients ce qu'il a reçu
     */
     int k =0;
     length = i + 1;
     for(k; k < length; k++) {
        n = sendto(sockfd, buf, strlen(buf), 0, 
                  (struct sockaddr *) clientaddr[k], clientlen);
        if (n < 0)
            error("error sendto");
    }
    i++;          
  }
  close(sockfd);

}

客户:

import java.awt.*;
import javax.swing.*;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.*;
import java.io.*;
import java.util.*;

public class IHM extends JFrame implements ActionListener{
    private static String mess;
    private Graphics g;
    private JPanel dessin=new JPanel();
    private JPanel zoneBouton=new JPanel();
    private JButton carre = new JButton("Carre");
    private JButton ligne = new JButton("Ligne");
    private JButton rond = new JButton("Rond");
    private JButton refresh = new JButton("Refresh");
    private DatagramSocket ds;
    private DatagramPacket dp;
    public IHM(){
        this.setTitle("IHM reseau");
        this.setLayout(new BorderLayout());
        this.setSize(800,500);
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        GridLayout gl = new GridLayout(4,1);
        zoneBouton.setLayout(gl);
        carre.addActionListener(this);
        rond.addActionListener(this);
        ligne.addActionListener(this);
        refresh.addActionListener(this);
        zoneBouton.add(carre, BorderLayout.WEST);
        zoneBouton.add(rond, BorderLayout.WEST);
        zoneBouton.add(ligne, BorderLayout.WEST);
        zoneBouton.add(refresh, BorderLayout.WEST);
        this.add(dessin, BorderLayout.CENTER);
        this.add(zoneBouton, BorderLayout.EAST);
        this.setVisible(true); 
    }
    public void paintComponent( Graphics g )
        {
            this.g = dessin.getGraphics();
            if(mess.contains("1") || mess.contains("carre"))
            {
                g.drawRect( 5, 40, 90, 55 );
                g.fillRect( 100, 40, 90, 55 );
            }
            if(mess.contains("2") || mess.contains("rond"))
            {
                g.setColor( Color.green );
                g.drawOval( 195, 100, 90, 55 );
                g.fillOval( 290, 100, 90, 55 );

            }
            if(mess.contains("3") || mess.contains("ligne"))
            {
                g.setColor( Color.BLUE );
                g.drawLine( 5, 30, 380, 30 ); 

            }
            if(mess.contains("4") || mess.contains("refresh"))
            {
                repaint();

            }
            this.mess = "";
            //super.paintComponent(g);
            //super.paintComponent(g);
    }
    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource().equals(this.carre)){
            String message1 = "1";
            try{
                this.ds = new DatagramSocket();
                DatagramPacket msg = new DatagramPacket(new byte[512], 512);
                DatagramPacket envoi = new DatagramPacket(message1.getBytes(),
                message1.length(),InetAddress.getByName("127.0.0.1"),8080);
                ds.send(envoi);
                this.dp = new DatagramPacket(new byte[512], 512);
                ds.receive(dp);
                this.mess = new String(dp.getData());
            }
            catch(UnknownHostException i){}
            catch(IOException i){}
            message1 = "";
        }
        if(e.getSource().equals(this.rond)){
            String message2 = "2";
            try{
                this.ds = new DatagramSocket();
                DatagramPacket msg = new DatagramPacket(new byte[512], 512);
                DatagramPacket envoi = new DatagramPacket(message2.getBytes(),
                message2.length(),InetAddress.getByName("127.0.0.1"),8080);
                ds.send(envoi);
                this.dp = new DatagramPacket(new byte[512], 512);
                ds.receive(dp);
                this.mess = new String(dp.getData());
            }
            catch(UnknownHostException i){}
            catch(IOException i){}
            message2 = "";
        }
        if(e.getSource().equals(this.ligne)){
            String message3 = "3";
            try{
                this.ds = new DatagramSocket();
                DatagramPacket msg = new DatagramPacket(new byte[512], 512);
                DatagramPacket envoi = new DatagramPacket(message3.getBytes(),
                message3.length(),InetAddress.getByName("127.0.0.1"),8080);
                ds.send(envoi);
                this.dp = new DatagramPacket(new byte[512], 512);
                ds.receive(dp);
                this.mess = new String(dp.getData());
            }
            catch(UnknownHostException i){}
            catch(IOException i){}
            message3 = "";
        }
        if(e.getSource().equals(this.refresh)){
            String message4 = "4";
            try{
                this.ds = new DatagramSocket();
                DatagramPacket msg = new DatagramPacket(new byte[512], 512);
                DatagramPacket envoi = new DatagramPacket(message4.getBytes(),
                message4.length(),InetAddress.getByName("127.0.0.1"),8888);
                ds.send(envoi);
                this.dp = new DatagramPacket(new byte[512], 512);
                ds.receive(dp);
                this.mess = new String(dp.getData());
            }
            catch(UnknownHostException i){}
            catch(IOException i){}
            message4 = "";
        }
        System.out.println(mess);
        this.paintComponent(this.g);
        validate();
    }
        // Fonction principale
        public static void main (String[] args)
        {
            new IHM();
        }
}

1 个答案:

答案 0 :(得分:2)

struct sockaddr_in *clientaddr;

被指定为struct sockaddr_in的指针,但你在循环中使用它就像struct sockaddr_in数组一样:

sendto(sockfd, buf, strlen(buf), 0, 
       (struct sockaddr *) &clientaddr[k], clientlen);

您可以将clientaddr作为指向sockaddr_in的指针数组:

#define MAX_CLIENTS 1000
struct sockaddr_in *clientaddr[MAX_CLIENTS];
// in main loop:
clientaddr[i] = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
recvfrom(sockfd, buf, BUFSIZE, 0,
      (struct sockaddr *)clientaddr[i], &clientlen);

// send loop:
int k = 0;
length = i + 1;
for(k; k < length; k++) {
      n = sendto(sockfd, buf, strlen(buf), 0, 
       (struct sockaddr *) clientaddr[k], clientlen);
        if (n < 0)
          error("error sendto");
}