我正在尝试使用C ++学习网络,并且试图建立一个简单的演示,在该示例中,我在端口5000上打开一个TCP服务器,然后立即将其关闭。这是我的代码:
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
int port = 5000;
std::cout << "Port: " << port << "\n";
int socketdesc = socket(SOCK_STREAM, AF_INET, 0);
if (socketdesc == 0)
{
std::cout << "Failed to create socket description.\n";
return 1;
}
int opt = 1;
if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
std::cout << "Failed to attach socket.\n";
return 1;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(socketdesc, (struct sockaddr *)&address,
sizeof(address)) < 0)
{
std::cout << "Failed to bind socket!\n";
return 1;
}
std::cout << "Listening with protocol TCP on port" << port << ".\n";
if (listen(socketdesc, 3) < 0)
{
std::cout << "Failed to listen!\n";
return 1;
}
if (shutdown(socketdesc, SHUT_RDWR) < 0)
{
std::cout << "Failed to close socket!\n";
return 1;
}
std::cout << "TCP test succeeeded.\n";
return 0;
}
尝试将套接字绑定到端口5000时出现错误。设置TCP服务器端口出了什么问题?
P.S:opt位到底是什么(我正在关注一个教程,同时查看sys / socket的文档)?
答案 0 :(得分:1)
在您到达bind()
之前,您的代码中存在一些错误:
int socketdesc = socket(SOCK_STREAM,AF_INET,0);
您将前两个参数值向后移动,则调用应改为如下所示:
int socketdesc = socket(AF_INET, SOCK_STREAM, 0);
如果(socketdesc == 0)
socket()
在错误时返回-1,而不是0。
如果(setsockopt(socketdesc,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT,&opt,sizeof(opt)))
setsockopt()
也会在错误时返回-1。
但更重要的是,您不能像这样在单个调用中组合多个套接字选项。您需要分别为每个选项调用setsockopt()
:
if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
...
if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0)
...
话虽如此,请尝试以下操作:
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int port = 5000;
std::cout << "Port: " << port << "\n";
int socketdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socketdesc == -1)
{
std::cout << "Failed to create socket descriptor. " << strerror(errno) << "\n";
return 1;
}
int opt = 1;
if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
{
std::cout << "Failed to set SO_REUSEADDR option. " << strerror(errno) << "\n";
return 1;
}
if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0)
{
std::cout << "Failed to set SO_REUSEPORT option. " << strerror(errno) << "\n";
return 1;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(socketdesc, (struct sockaddr *)&address, sizeof(address)) < 0)
{
std::cout << "Failed to bind socket! " << strerror(errno) << "\n";
return 1;
}
std::cout << "Listening with protocol TCP on port" << port << ".\n";
if (listen(socketdesc, 3) < 0)
{
std::cout << "Failed to listen on socket! " << strerror(errno) << "\n";
return 1;
}
if (shutdown(socketdesc, SHUT_RDWR) < 0)
{
std::cout << "Failed to close socket! " << strerror(errno) << "\n";
return 1;
}
close(socketdesc);
std::cout << "TCP test succeeeded.\n";
return 0;
}
答案 1 :(得分:0)
即使现在不是这种情况,我将在此处保留此答案。我认为这仍然是一个真实的案例,有人在网站上寻找答案可能会对此表示赞赏。
(上面代码的真正答案是在注释中)
您需要关闭套接字,但尚未在每个故障状态下都关闭。即使过程结束,它也会保持打开状态并阻止您再次绑定它。
如果不是这种情况,则可能有其他程序在使用该端口。尝试更改端口号。