C les Sockets Serveur bind() erreur
Tout se compile sans erreurs et des avertissements. Je commence le programme. Je visite localhost:8080 et le programme s'arrête - grand. J'essaie d'exécuter à nouveau le programme et j'ai d'Erreur: impossible de lier message. Pourquoi?
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PORT 8080
#define PROTOCOL 0
#define BACKLOG 10
int main()
{
int fd;
int connfd;
struct sockaddr_in addr; //For bind()
struct sockaddr_in cliaddr; //For accept()
socklen_t cliaddrlen = sizeof(cliaddr);
//Open a socket
fd = socket(AF_INET, SOCK_STREAM, PROTOCOL);
if (fd == -1) {
printf("Error: unable to open a socket\n");
exit(1);
}
//Create an address
//memset(&addr, 0, sizeof addr);
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
if ((bind(fd, (struct sockaddr *)&addr, sizeof(addr))) == -1) {
printf("Error: unable to bind\n");
printf("Error code: %d\n", errno);
exit(1);
}
//List for connections
if ((listen(fd, BACKLOG)) == -1) {
printf("Error: unable to listen for connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
//Accept connections
connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
//read(connfd, buffer, bufferlen);
//write(connfd, data, datalen);
// close(connfd);
return 0;
}
printf("Error code: %d\n", errno);
(ou utilisez perror ou strerror() ) BTW: le premier printf() pourrait probablement réinitialiser errno. BTW2: diagnostic de sortie devrait aller vers stderr.- whoopsie! Merci @wildplasser
- Et l'erreur que vous obtenez le deuxième temps est probablement "EADDRINUSE address already in use" ?
- OT: C'est
int main(void)
au moins.
Vous devez vous connecter pour publier un commentaire.
Utiliser le
SO_REUSEADDR
option de socket avant d'appelerbind()
, dans le cas où vous avez les anciennes connexions dansTIME_WAIT
ouCLOSE_WAIT
état.Les utilisations de SO_REUSEADDR?
Dans le but de savoir pourquoi, vous avez besoin d'imprimer l'erreur; la raison la plus probable est qu'un autre programme utilise déjà le port (
netstat
peut vous dire).Votre problème d'impression est que C les chaînes de format utiliser
%
, pas&
. Remplacer un caractère dans la chaîne d'impression, et cela devrait fonctionner.Tout d'abord, avoir un coup d'oeil dans l'exemple suivant:
Serveur Socket Exemple
Deuxième: La raison pour laquelle le deuxième lier échoue, parce que votre application s'est écrasé, le socket est encore lié pour un certain nombre de secondes, voire quelques minutes.
Vérifier avec la commande "netstat" commande si la connexion est toujours ouverte.
Essayer de mettre le code suivant juste avant de bind()
int opt = 1;
if (setsockopt(<Master socket FD>, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))<0) {perror("setsockopt");exit(EXIT_FAILURE);}if(setsockopt(<Master socket FD>, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(opt))<0) {
perror("setsockopt");exit(EXIT_FAILURE);}
Raison derrière socket bind erreur 98:
Socket est 4 n-uplet (ip du serveur, le port du serveur , l'ip du client, le client de port)
Lorsque l'un des deux supports tuples matches , erreur de 98 est levée
Lorsque vous résiliez le code côté serveur, cela signifie que vous êtes de fin de la connexion avec le client tcp .
Maintenant le serveur est celui qui envoie FIN de client et va à l'état TIME_WAIT.
Généralement , dans l'état TIME_WAIT serveur envoie des paquets d'accusé de réception en continu pour le client , en supposant que si aucun accusé de réception est perdu entre les deux .
Le temps qu'il dépend de la mise en œuvre du code . Il pourrait être de 30 secondes à 2 minutes ou plus.
Si vous exécutez à nouveau le code , le serveur est en TIME_WAIT , hecne port est déjà en cours d'utilisation . C'est parce que tout service qui s'exécute sur le serveur utilisera port fixe qui n'est pas le cas avec le client .
C'est pourquoi, dans la vraie vie, le serveur n'enverra jamais de FIN pour le client .C'est le client qui envoie FIN pour mettre fin à la connexion.
Même si le client se connecte à nouveau avant expiration de TIME_WAIT, il sera connecté au serveur , car, il utilisera désormais un port différent donc socket tuple changements .
Si elle est mise en œuvre dans le sens inverse , si le serveur envoie FIN , après toute nouvelle connexion ne serait pas accepter jusqu'délai d'attente termine .
Pourquoi le port est occupé ?
C'est parce que dans TIME_Wait , celui qui envoie FIN de la première, doit transmettre des paquets d'accusé de réception en continu jusqu'délai expire.