C语言 C 服务器套接字 - bind() 错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22126940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C Server Sockets - bind() error
提问by chuckfinley
Everything compiles without errors and warnings. I start the program. I visit localhost:8080 and the program stops - great. I try to run the program again and I get Error: unable to bindmessage. Why?
一切都编译没有错误和警告。我启动程序。我访问 localhost:8080 并且程序停止了 - 太好了。我尝试再次运行该程序,但出现错误:无法绑定消息。为什么?
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;
}
回答by Barmar
Use the SO_REUSEADDRsocket option before calling bind(), in case you have old connections in TIME_WAITor CLOSE_WAITstate.
SO_REUSEADDR在调用之前使用套接字选项bind(),以防您在TIME_WAIT或CLOSE_WAIT状态中有旧连接。
回答by chrylis -cautiouslyoptimistic-
In order to find out why, you need to print the error; the most likely reason is that another program is already using the port (netstatcan tell you).
为了找出原因,您需要打印错误;最可能的原因是另一个程序已经在使用该端口(netstat可以告诉你)。
Your print problem is that C format strings use %, not &. Replace the character in your print string, and it should work.
您的打印问题是 C 格式字符串使用%,而不是&. 替换打印字符串中的字符,它应该可以工作。
回答by Flovdis
First, have a look into the following example: Socket Server Example
首先,看看下面的例子: Socket Server Example
Second: The reason why the second bind fails is, because your application crashed, the socket is still bound for a number of seconds or even minutes.
第二:第二次绑定失败的原因是,因为你的应用程序崩溃了,socket仍然绑定了几秒甚至几分钟。
Check with the "netstat" command if the connection is still open.
如果连接仍然打开,请使用“netstat”命令检查。
回答by V SAI MAHIDHAR
Try putting the following code just before bind()
尝试将以下代码放在 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);}
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);}
Reason behind socket bind error 98:
套接字绑定错误 98 背后的原因:
Socket is 4 tuple (server ip, server port , client ip, client port) When any two sockets tuples matches , error 98 is thrown When you terminate the code on server side, it means you are ending connection with tcp client . Now server is the one which sends FIN to client and goes to TIME_WAIT state. Typically , in TIME_WAIT sate server sends ack packets continuously to client , assuming that if any ack gets lost in between . Time out it depends on implementation of code . It could be from 30 seconds to 2 minutes or more.
Socket is 4 tuple (server ip, server port , client ip, client port) 当任意两个套接字元组匹配时,会抛出错误 98 当您在服务器端终止代码时,这意味着您正在终止与 tcp client 的连接。现在服务器是将 FIN 发送到客户端并进入 TIME_WAIT 状态的服务器。通常,在 TIME_WAIT 状态下,服务器会连续向客户端发送 ack 数据包,假设在这两者之间丢失了任何 ack。超时取决于代码的实现。它可以是 30 秒到 2 分钟或更长时间。
If you run the code again , server is in TIME_WAIT , hecne port is already in use . This is because any service running on server will use fixed port which is not the case with client .
如果再次运行代码,服务器处于 TIME_WAIT 状态,hecne 端口已在使用中。这是因为在 server 上运行的任何服务都将使用固定端口,而 client 则不是这种情况。
That is why in real life, server will never send FIN to client .It is client who sends FIN in order to end connection. Even if client connects again before timeout of TIME_WAIT, he will be connected to server because , he will use now a different port thus socket tuple changes . If it is implemented in reverse way , if server sends FIN , there after any new connection would not be accept till timeout ends .
这就是为什么在现实生活中,服务器永远不会向客户端发送 FIN。客户端发送 FIN 以结束连接。即使客户端在 TIME_WAIT 超时之前再次连接,他也会连接到服务器,因为他现在将使用不同的端口,因此套接字元组会发生变化。如果以相反的方式实现,如果服务器发送 FIN,则在超时结束之前不会接受任何新连接。
Why port is busy ? It is because in TIME_Wait , the one who sends FIN first, must transmit ack packets continuously till timeout expires.
为什么端口很忙?这是因为在 TIME_Wait 中,首先发送 FIN 的人必须连续发送 ack 数据包,直到超时到期。

