我想向我的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();
}
}
答案 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");
}