f.ben.isaac
November 9th, 2008, 12:34 AM
I got a weird problem. I coded a server. Works good, but it only binds the port to the local IPv6 .... So when the client enters the target external IP (Usually IPv4)/port. Client will be able to connect to the listening port that is through IPv4 only...
For example, i made my server binds on port 4443 on the local machine...
I check netstat -an, i get
Proto Local Address Foreign Address State
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING
TCP 0.0.0.0:1025 0.0.0.0:0 LISTENING
TCP [::]:135 [::]:0 LISTENING
TCP [::]:445 [::]:0 LISTENING
TCP [::]:1025 [::]:0 LISTENING
TCP [::]:4443 [::]:0 LISTENING
ports 135, 445, and 1025 will respond to client who connects to it through IPv4 or IPv6. 4443 will only respond to client who connects to it through IPv6. So for a client to connect on the server port 4443, it (client) must enter IPv6 for the target so 4443 can respond. Otherwise, connection will fail as you see that 4443 is not included among IPv4! I hope you get my point.....Weird problem! ..... On linux, everything works fine, but on Vista things did not go as it should be....
I hope somebody can provide some help...
egawtry
November 9th, 2008, 11:19 AM
Post some code.
f.ben.isaac
November 9th, 2008, 12:18 PM
Not a perfect code, i just did it to practice on it roughly, so the code uses mixture of C/C++ .... It worked under linux...Once i ported into windows, i faced the problem i mentioned above...
#include<iostream>
#include<string>
#include<sstream>
#include"Winsock2.h" //VC++
#include<Ws2tcpip.h> //VC++
#include<Winerror.h> //VC++
using namespace std;
#define BACKLOG 2 // how many pending connections queue will hold
#define MAX_DATA 1024 //maximum bytes that could be sent or received
//describe the program
void progDesc()
{
cout<<"This server listens for a connection from client, and waits\n";
cout<<"some data from client. Server echos back same message to client."<<endl;
}
//get sockaddr, IPv4 or IPv6:
void *get_client_addr(struct sockaddr_storage *clientInformation)
{
void *addr;
if (clientInformation->ss_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)clientInformation;
addr = &(ipv4->sin_addr);
return addr;
}else{
addr = &( ((struct sockaddr_in6 *)clientInformation)->sin6_addr );
return addr;
}
}
u_short get_client_port(struct sockaddr_storage *clientInformation)
{
u_short portNumber;
if (clientInformation->ss_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)clientInformation;
portNumber = ipv4->sin_port;
return portNumber;
}else{
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)clientInformation;
portNumber = ipv6->sin6_port;
return portNumber;
}
}
int main()
{
SOCKET serverSockD;
SOCKET clientSockD;
struct addrinfo hints;
struct addrinfo *servInfo;
struct sockaddr_storage clientInfo;
int clientInfo_size;
char *listenPort = new char[10];
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
cout<<"Choose a port to listen on: ";
cin>>listenPort;
//set size of hints to zero
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int status = getaddrinfo(NULL, listenPort, &hints, &servInfo);
if(status == -1)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
WSACleanup();
return 1;
}
serverSockD = socket(servInfo->ai_family, servInfo->ai_socktype, servInfo->ai_protocol);
if(serverSockD == INVALID_SOCKET )
{
cout<<"Error: failed to create a socket.\n";
closesocket(serverSockD);
WSACleanup();
return 2;
}
//****bind socket to ip/port
if(bind(serverSockD, servInfo->ai_addr, servInfo->ai_addrlen) == SOCKET_ERROR)
{
perror("server: bind");
closesocket(serverSockD);
WSACleanup();
return 3;
}
//****socket should be listening - open
if(listen(serverSockD, BACKLOG) == SOCKET_ERROR)
{
perror("listen");
closesocket(serverSockD);
WSACleanup();
return 4;
}
cout<<"waiting for a connection ... "<<endl;
clientInfo_size = sizeof clientInfo;
int bytes_received;
char data[MAX_DATA];
char printableClientIP[INET6_ADDRSTRLEN];
void *clientIP;
u_short portNum;
//keep listening until you kill the server process
while(1)
{
clientSockD = accept(serverSockD, (struct sockaddr *)&clientInfo, &clientInfo_size);
if(clientSockD == INVALID_SOCKET )
{
cout<<"ERROR: "<<WSAGetLastError()<<endl;
closesocket(clientSockD);
closesocket(serverSockD);
WSACleanup();
return 5;
}
clientIP = get_client_addr(&clientInfo);
portNum = get_client_port(&clientInfo);
inet_ntop(clientInfo.ss_family, clientIP, printableClientIP, sizeof printableClientIP);
u_short portHostByte = ntohs(portNum);
printf("New Client connected from port no. %d and IP %s\n", portHostByte, printableClientIP);
bytes_received = 1;
while(bytes_received > 0)
{
bytes_received = recv(clientSockD, data, MAX_DATA, 0);
if(bytes_received > 0)
{
send(clientSockD, data, bytes_received, 0);
data[bytes_received] = '\0';
printf("Sent mesg: %s", data);
}
}
printf("Client disconnected\n");
closesocket(clientSockD);
}
closesocket(serverSockD);
delete[] listenPort;
freeaddrinfo(servInfo);
WSACleanup();
return 0;
}
egawtry
November 9th, 2008, 04:49 PM
Change
hints.ai_family = AF_UNSPEC;
to
hints.ai_family = AF_INET;
to do IPV4. With AF_UNSPEC, then things will connect with the highest numbered family protocol which happens to be IPV6 with Windows.
-Erik
f.ben.isaac
November 9th, 2008, 05:08 PM
Haa! Duh, how come i did not realize it.... I will check it out later & let you know....
Your help is much appreciated...
f.ben.isaac
November 9th, 2008, 05:45 PM
Worked....Many thanks!