ソケットライブラリを作成していますが、特定のアドレスとポートにバインドするクライアントソケットで問題が発生しています。現在、winsock TCPライブラリをテストしていますが、*nixで同じ問題が発生しない理由はないと確信しています。これまでのところ、すべてが正常に機能しています(最初にconnect()
電話をかけなくても、できます)。bind()
send()
recv()
192.168.1.99:XXXX(私のマシンのアドレス)をリッスンしているサーバーがあります。
次に、ソケットを取得して192.168.1.99:0にバインドします。WSAEADDRNOTAVAIL
接続しようとすると、ソケットエラー10049( )が発生します。0.0.0.0:0にバインドしようとすると、同じことが起こります。
127.0.0.1:0またはlocalhostにバインドしようとするか、ホスト名をNULLのままにしようとすると(これが可能な場合でも、AI_PASSIVEフラグを使用する必要がありますか?)、接続すると10061(WSACONNREFUSED
)が返されます。
ここでこれを行う正しい方法を知っている人はいますか?
EDIT3:問題は、bindを呼び出す前にソケットを呼び出していて、connectを呼び出す前にもう一度ソケットを呼び出していたことでした。bindを呼び出す前にソケットのみを呼び出すように切り替えました。他の誰かがこの概念全体に混乱しているかどうかわからないので、誰かがそれを閉じるべきだと感じない限り、これをここに残しておきますか?
編集2:ソケットを2回呼び出すという問題はありますか?
編集:ここにいくつかの機能があります
int main() {
WSADATA wsaData; // if this doesn't work
if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
cout << WSAStartup failed << endl;
return -1;
}
ClientSocket* cs = new ClientSocket("192.168.1.99", "XXXX");
cs->bind("", "0"); //error 10049 (WSAEADDRNOTAVAIL)
//cs->bind("", "60000"); //error 10049 (WSAEADDRNOTAVAIL)
//cs->bind("0.0.0.0", "0"); //error 10049 (WSAEADDRNOTAVAIL)
//cs->bind("0.0.0.0", "60000"); //error 10049 (WSAEADDRNOTAVAIL)
//cs->bind("192.168.1.99", "0"); //error 10061 (WSACONNREFUSED)
//cs->bind("192.168.1.99", "60000"); //error 10061 (WSACONNREFUSED)
//cs->bind("127.0.0.1", "0"); //error 10061 (WSACONNREFUSED)
//cs->bind("127.0.0.1", "60000"); //error 10061 (WSACONNREFUSED)
//cs->bind("localhost", "0"); //error 10061 (WSACONNREFUSED)
//cs->bind("localhost", "60000"); //error 10061 (WSACONNREFUSED)
cs->connect(); //connects to the info passed in ctor
Socket* s = cs->getSocket();
if(s == NULL) {
cs->close();
return -1;
}
.
.
.
.
}
//these are the methods exposed by my API
int ClientSocket::bind(std::string hostname, std::string port) {
if(bound) {
return -1;
}
if(connected) {
return -2;
}
//this defines what specialSockOp will do
ssop = &ClientSocket::BaseDef::bind;
info->hostname = hostname;
if(hostname.compare("") == 0) {
info->AI_FLAG_PASSIVE = true;
}
info->port = port;
//calls SpecialSocket::socket()
socket();
bound = true;
return 0;
}
int ClientSocket::connect() {
if(connected) {
return SOCKET_ERROR;
//throw exception
}
if(bound) {
ssop = &ClientSocket::BaseDef::connect;
}
socket();
return 0;
}
void SpecialSocket::WinImp::socket() {
struct addrinfo *results = NULL, *p = NULL, hints;
int rv;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = (containerClass->info->ipType == IP_DUAL ? AF_UNSPEC :
containerClass->info->ipType == IPV6 ? AF_INET6 : AF_INET);
hints.ai_socktype = (containerClass->info->protocol == TCP ? SOCK_STREAM :
SOCK_DGRAM);
hints.ai_protocol = 0;
if(containerClass->info->AI_FLAG_PASSIVE) {
hints.ai_flags |= AI_PASSIVE;
}
if(containerClass->info->AI_FLAG_CANONNAME) {
hints.ai_flags |= AI_CANONNAME;
}
//cStringHostname returns NULL if an empty string has been passed in
if((rv = getaddrinfo(containerClass->info->cStringHostname(),
containerClass->info->cStringPort(), &hints, &results)) != 0) {
//throw exception
}
for(p = results; p != NULL; p = p->ai_next) {
if((containerClass->info->sock_fd = ::socket(p->ai_family,
p->ai_socktype, p->ai_protocol)) == INVALID_SOCKET) {
closesocket(containerClass->info->sock_fd);
continue;
}
//for a ClientSocket specialSockOp will call either bind or connect
//corresponding to the function called by ClientSocket
if(containerClass->specialSockOp(p->ai_addr) == SOCKET_ERROR) {
closesocket(containerClass->info->sock_fd);
continue;
}
break; //successfully connected
}
if(p == NULL) {
//none of the connections in results were good
//throw exception - could not connect
}
freeaddrinfo(results);
}
int SpecialSocket::WinImp::bind(const void* addr) {
struct sockaddr* ai_addr = (struct sockaddr*)addr;
return ::bind(containerClass->getSockFd(), ai_addr, sizeof(*ai_addr));
}
int ClientSocket::WinImp::connect(const void* addr) {
struct sockaddr* ai_addr = (struct sockaddr*)addr;
int result = ::connect(containerClass->getSockFd(), ai_addr, sizeof(*ai_addr));
if(result == SOCKET_ERROR) {
//these are where my errors are showing up
cout << "error after connect() is - " << WSAGetLastError() << endl;
return SOCKET_ERROR;
}
containerClass->servInfo->sock_fd = containerClass->getSockFd();
//I separated the functionality here - Socket can only send/recv
containerClass->s = new Socket();
//I use getpeername here to get information about the remote socket
//Long story but basically sets up the Socket
containerClass->initRWSocket(containerClass->s, containerClass->servInfo);
return result;
}
その後、ユーザーは電話をかけることができ、それClientSocket.getSocket()
を返すSocket
ことができsend/recv
ます。私の場合、インスタンス化される前に戻るため、インスタンス化されないため、これNULL
が返されます。Socket
SpecialSocket::connect