Windows socket api 绑定函数编译问题
Posted
技术标签:
【中文标题】Windows socket api 绑定函数编译问题【英文标题】:Windows socket api bind function compile issues 【发布时间】:2013-04-07 21:37:35 【问题描述】:我正在尝试在 Windows 上绑定一个 tcp 套接字,当期望从函数返回一个整数时,我得到一个编译错误。我不是 C++ 程序员,通常不在 Windows 上工作,所以我无法追踪这个问题。我确实注意到的一件事是,如果我没有包含 winsock 头文件,那么我使用的所有其他处理套接字的函数(例如 send、recv、accept 和 connect)都会引发编译错误,但没有为 bind 函数引发一个错误。这让我相信我是如何引入不同的绑定函数而不是我所期望的。
整个应用程序包含的头文件列表
#include <fstream>
#include <string>
#include <ctime>
#include <mutex>
#include <stdio.h>
#include <strsafe.h>
#include <map>
#include <iterator>
#include <process.h>
#include <queue>
#include <iostream>
#include <winsock.h>
包含的库是
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "User32.lib")
而试图使用绑定函数的类是
//implement an interface for udp and tcp socket classes to implement
class Socket
public:
virtual void sendm(const char *buf) = 0;
virtual int recvm(char *buf) = 0;
struct hostent *phe; /* pointer to host information entry */
struct servent *pse; /* pointer to service information entry */
struct protoent *ppe; /* pointer to protocol information entry */
struct sockaddr_in sin; /* an Internet endpoint address */
int type, status; /* socket descriptor and socket type */
SOCKET s; /* socket */
;
class TCPSocket : public Socket
public:
TCPSocket(const char *host, const char *service, bool master_socket)
initialize_socket(host, service, master_socket);
~TCPSocket(void);
SOCKET initialize_socket(const char *host, const char *service, bool master_socket)
cout << "host: " << host << endl;
cout << "service: " << service << endl;
char* transport = "tcp";
int qlen = 10;
int portbase = 0;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
if (pse = getservbyname(service, transport) )
sin.sin_port = htons(ntohs((u_short)pse->s_port) + portbase);
else if ((sin.sin_port = htons((u_short)atoi(service))) == 0)
cout << "can't get " << service << " service" << endl;
exit(1);
/* Map protocol name to protocol number */
if ( (ppe = getprotobyname(transport)) == 0)
cout << "Can't get \"" << transport << "\" protocol entry "<< endl;
exit(1);
/* Map host name to IP address, allowing for dotted decimal */
if (master_socket)
sin.sin_addr.s_addr = htonl( INADDR_ANY );
else
if ( phe = gethostbyname(host) )
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
cout << "Can't get \"" << host << "\" IP address "<< endl;
exit(1);
type = SOCK_STREAM;
s = socket(AF_INET, type, ppe->p_proto);
if (s == INVALID_SOCKET)
cout << "Socket Error: " << GetLastError() << endl;
exit(1);
if (master_socket)
status = bind(s, (sockaddr *)&sin, sizeof(sin));
/* if (status != 0) */
/* cout << "Bind Error: " << service << " port: " << GetLastError(); */
/* */
status = listen(s, qlen);
if (status != 0)
cout << "can't listen on " << service << " port: " << GetLastError();
exit(1);
else
int status = connect(s, (struct sockaddr*)&sin, sizeof(sin));
if ( status != 0 )
cout << "could not connect" << endl;
exit(1);
return s;
SOCKET acceptSocket()
return accept(s, (struct sockaddr*)&sin, (int*)sizeof(sin));
void sendm(const char *buf)
send(s, buf, strlen(buf), 0);
int recvm(char *buf)
return recv(s, buf, BUFFER_SIZE, 0);
;
msdn 上bind 上的文档说此函数返回一个 int。
我在尝试编译时遇到的编译错误是
error C2440: '=' : cannot convert from 'std::_Bind<_Forced,_Ret,_Fun,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t,_V5_t,<unnamed-symbol>>' to 'int'
with
[
_Forced=false,
_Ret=void,
_Fun=SOCKET &,
_V0_t=sockaddr *,
_V1_t=unsigned int,
_V2_t=std::_Nil,
_V3_t=std::_Nil,
_V4_t=std::_Nil,
_V5_t=std::_Nil,
<unnamed-symbol>=std::_Nil
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
我正在使用在 VirtualBox 中的 VM 上运行的 Windows 8。我正在使用 Visual Studios 2012 命令开发人员命令行来编译我的代码。任何关于为什么 bind 不能按预期工作的建议都将非常感激。
【问题讨论】:
【参考方案1】:这让我相信我是一个与众不同的人 绑定函数然后我期待。
是的,您正在拉入std::bind。如果您查看<mutex>
内部,则它具有#include <functional>
这一行,其中包括std::bind
。
您可能在某处有一个using namespace std;
,它使std
命名空间中的所有名称都可见。
另外,你想要的绑定在Winsock2.h
,我没有看到#include
。
请阅读Why is 'using namespace std;' considered a bad practice in C++?。我建议删除任何 using 指令(这可能是导致此问题的原因)并完全限定所有内容。
【讨论】:
一旦包含部分被修复,将bind
正确地限定为::bind
- 或用于该功能的任何命名空间windows API - 应该可以解决问题。
非常感谢您解决了这个问题。我使用的是 mutex 绑定函数,而不是使用正确的 winsock 标头。【参考方案2】:
当使用<mutex>
并有“使用命名空间标准”时
使用::bind()
而不是bind()
【讨论】:
以上是关于Windows socket api 绑定函数编译问题的主要内容,如果未能解决你的问题,请参考以下文章
Windows 环境下的 Socket 编程 1 - 环境搭建和 Socket 相关函数
Windows 环境下的 Socket 编程 1 - 环境搭建和 Socket 相关函数
Windows 环境下的 Socket 编程 1 - 环境搭建和 Socket 相关函数
socket编程:bind函数是把socket绑定到具体窗口?