我是网络编程的新手,并且从A Simple Stream Server
中的http://beej.us/guide/bgnet/html/multi/clientserver.html#figure2重写了Visual Studio 2015
。在这里,我仅发布部分代码(直到freeaddrinfo(servinfo)
),因为该问题已经存在。
// StreamServer.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <errno.h>
#include <string>
#include <sys/types.h>
#include "WinSock2.h"
#include "ws2ipdef.h"
#include "WS2tcpip.h"
#define PORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
// get sockaddr, IPv4 or IPv6:
void* get_in_addr(struct sockaddr* sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main()
{
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
std::cout << "WSAStartup failed." << std::endl;
exit(1);
}
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) == -1) {
return 1;
}
// loop through all the results and bind to the first we can
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol) == -1)) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
closesocket(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo);
WSACleanup();
return 0;
}
setsockopt(...)
失败,并将errno
变量设置为0
。我还打印了错误,并显示No error
。我不明白我做错了什么。我以为程序应该已经在指定的端口上运行并等待,直到某些客户端将数据发送到该端口。
答案 0 :(得分:1)
你有点混用习惯。
perror
来自Linux(或更广泛地说,与POSIX兼容的系统)上的编程,并且会告诉您errno
是什么。
但是Windows不使用errno
!要从Windows套接字函数获取错误,您需要WSAGetLastError()
。那应该告诉您您做错了什么(在这种情况下,为SO_REUSEADDR
传递了错误的参数)。