I'm struggling to make sense of this. The issue is seen on a machine that is:
Remote (I do not have access to it)
Running Windows 7
NOT running a proxy or VPN (or so I have been told)
My application has a snippet of code that tries to quickly determine which interface the OS prefers. It does the following:
// Create a socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
// Resolve DNS query
DWORD dwRemoteIp = GetHostAddr("www.google.com")
// I've simplified the call here, but "www.google.com" resolves to 172.217.3.100 in host byte order, so the resolution is correct
// Create the remote address to connect to
sockaddr_in remoteaddr = {0};
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = htonl(dwRemoteIp);
remoteaddr.sin_port = htons(80);
// Connect the socket
if (0 == connect(sock, (struct sockaddr*)&remoteaddr, sizeof(remoteaddr))) {
// The connection succeeded -- see which local address was bound to
sockaddr_in localaddr = {0};
int len = sizeof(localaddr);
if (0 == getsockname(sock, (struct sockaddr*)&localaddr, (socklen_t *)&len)) {
// Here is where I see dwLocalIp == 0x7F000001, or 127.0.0.1
DWORD dwLocalIp = ntohl(localaddr.sin_addr.s_addr);
}
}
What could be going on here?
Related
I have a functional server code with only TCP connection. Now I want the server to receive from UDP connection. I have used port 2000 for TCP & port 2001 for UDP. Here is a snippet of my code
struct timeval timeout; // timeout for select(), 1ms
timeout.tv_sec = 0;
timeout.tv_usec = 1000;
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
int fdmax; // maximum file descriptor number
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
// TCP port setup
int sockfd; // listening socket descriptor
int newsockfd; // newly accept()ed socket descriptor
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
char buf_tcp[256]; // buffer for client data
char buf_copy_tcp[256];
int recv_bytes;
char remoteIP[INET6_ADDRSTRLEN];
int yes=1; // for setsockopt() SO_REUSEADDR
int i, k, rv_getaddrinfo, rv_setsockopt, rv_bind, rv_listen, rv_select;
struct addrinfo hints, *servinfo, *ptr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
rv_getaddrinfo = getaddrinfo(NULL, "2000", &hints, &servinfo);
for(ptr=servinfo; ptr!=NULL; ptr=ptr->ai_next)
{
sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
rv_setsockopt = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
rv_bind = bind(sockfd, ptr->ai_addr, ptr->ai_addrlen);
break;
}
if (ptr == NULL)
{
fprintf(stderr, "CLI Server error: failed to bind\n\r");
exit(2);
}
freeaddrinfo(servinfo); // all done with this
rv_listen = listen(sockfd, 10);
////////////////////////////////////////////////////////////////////////////////////////////////
// UDP port setup
int sockfd_udp; // listening socket descriptor
struct sockaddr_storage remoteaddr_udp; // client address
socklen_t addrlen_udp;
char buf_udp[256]; // buffer for client data
char buf_copy_udp[256];
int recv_bytes_udp;
char remoteIP_udp[INET6_ADDRSTRLEN];
int yes_udp=1; // for setsockopt() SO_REUSEADDR
int j, rv_getaddrinfo_udp, rv_setsockopt_udp, rv_bind_udp;
struct addrinfo hints_udp, *servinfo_udp, *ptr_udp;
memset(&hints_udp, 0, sizeof(hints_udp));
hints_udp.ai_family = AF_UNSPEC;
hints_udp.ai_socktype = SOCK_DGRAM;
hints_udp.ai_flags = AI_PASSIVE;
rv_getaddrinfo_udp = getaddrinfo(NULL, "2001", &hints_udp, &servinfo_udp);
for(ptr_udp=servinfo_udp; ptr_udp!=NULL; ptr_udp=ptr_udp->ai_next)
{
sockfd_udp = socket(ptr_udp->ai_family, ptr_udp->ai_socktype, ptr_udp->ai_protocol);
rv_setsockopt_udp = setsockopt(sockfd_udp, SOL_SOCKET, SO_REUSEADDR, &yes_udp, sizeof(int));
rv_bind_udp = bind(sockfd_udp, ptr_udp->ai_addr, ptr_udp->ai_addrlen);
break;
}
if (ptr_udp == NULL)
{
fprintf(stderr, "CLI UDP Server error: failed to bind\n\r");
exit(2);
}
freeaddrinfo(servinfo_udp); // all done with this
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// add the listener to the master set
FD_SET(sockfd, &master);
FD_SET(sockfd_udp, &master);
// keep track of the biggest file descriptor
if(sockfd > sockfd_udp)
fdmax = sockfd; // so far, it's this one
else
fdmax = sockfd_udp; // so far, it's this one
do
{
read_fds = master; // copy it
rv_select = select(fdmax+1, &read_fds, NULL, NULL, &timeout);
// run through the existing connections looking for data to read
for(i=0; i<=fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{ // we got one!!
if (i == sockfd)
{
// handle new connections
addrlen = sizeof(remoteaddr);
newsockfd = accept(sockfd, (struct sockaddr *)&remoteaddr, &addrlen);
FD_SET(newsockfd, &master); // add to master set
if (newsockfd > fdmax) // keep track of the max
fdmax = newsockfd;
inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr*)&remoteaddr), remoteIP, INET6_ADDRSTRLEN);
fprintf(stdout, "CLI Server: new connection from %s on socket %d\n\r", remoteIP, newsockfd);
}
else if (i == sockfd_udp)
{
// handle new udp connections
addrlen_udp = sizeof(remoteaddr_udp);
recv_bytes_udp = recvfrom(i, buf_udp, sizeof(buf_udp), 0, (struct sockaddr *)&remoteaddr_udp, &addrlen_udp);
inet_ntop(remoteaddr_udp.ss_family, get_in_addr((struct sockaddr*)&remoteaddr_udp), remoteIP_udp, INET6_ADDRSTRLEN);
for(j=0; j<=recv_bytes_udp; j++)
{
if( (buf_udp[k] == '\r') | (buf_udp[k] == '\n') )
buf_udp[k] = '\0';
}
fprintf(stdout, "CLI UDP Server: received %s from connection %s\n\r", buf_udp, remoteIP_udp);
}
else
{ // handle data from a client
if ((recv_bytes = recv(i, buf_tcp, sizeof(buf_tcp), 0)) <= 0)
{ // got error or connection closed by client
if (recv_bytes == 0) // connection closed
{
fprintf(stdout, "CLI Server: socket %d hung up\n\r", i);
}
else
{
perror("CLI Server error: recv");
exit(6);
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
}
else
{
for(k=0; k<=recv_bytes; k++)
{
if( (buf_tcp[k] == '\r') | (buf_tcp[k] == '\n') )
buf_tcp[k] = '\0';
}
fprintf(stdout, "CLI Server: received %s from socket %d\n\r", buf_tcp, i);
}
} // END handle data from client
} // END got new incoming connection
} // END looping through file descriptors
} while(QUIT);
I am doing error checking at each stage but didn't include it in the snippet. When I compile & run this, I can connect to port 2000 but not to 2001, my Tera term terminal closes with connection refused message. Why is the client not able to connect to port 2001 (UDP socket) but connects to port 2000 (TCP socket). The server just responds to client messages until client enters QUIT.
I have modeled this code from Beej's Guide to Network Programming selectserver.c code.
The program that I wrote above was correct but my understanding of socket programming was not. It was a fluke that I managed to write correct code but thanks to #EJP for having an extended discussion in the comments to clear up my doubt.
My mistake was using Teraterm's TCP client to connect to a UDP server. Both communications are mutually exclusive & hence can't communicate with one another. So I had to use a UDP client. Netcat provides an option of UDP client using netcat -u <ip address> <port>. Then my UDP server was able to receive messages from UDP client.
Another mistake was confusing bind() with connect() in DATAGRAM sockets. A connected DGRAM is when I use connect on both server & client.
I thought the problem was with select(), as I wrongly thought that UDP & TCP sockets can't be used simultaneously in select(). But the above code is how you write a UDP/TCP server for multiple client.
Thanks again to Beej & #EJP
How to reset an accepted socket in application level either with IO::Socket::INET in perl or in C?
There is a programm binding, listening on a TCP port, and accepts a client connection, after that it reads and writes some data.
If I simply close or shutdown the socket, TCP layer gracefully terminates (with FIN packet), rather than, I'd generate an RST packet.
You didn't specify the exact OS you are using. I found that Linux does have an API call which will reset a TCP connection, I have no idea how portable it is. The way to do it is to use the connect system call on the already connected socket but this time with family AF_UNSPEC.
After you have reset a socket that way it is even possible to connect the socket again with another connect call.
int main(int argc, char** argv)
{
int fd = socket(AF_INET6, SOCK_STREAM, 0);
while (1) {
struct sockaddr_in6 sockaddr = {
.sin6_family = AF_INET6,
.sin6_port = htons(80),
.sin6_flowinfo = 0,
.sin6_scope_id = 0,
};
struct timespec s = {
.tv_sec = 2,
.tv_nsec = 0,
};
/* Connect to port 80 on localhost */
inet_pton(AF_INET6, "::1", &sockaddr.sin6_addr.s6_addr);
connect(fd, (struct sockaddr*)&sockaddr,sizeof(sockaddr));
nanosleep(&s, NULL);
/* Reset previously connected socket */
sockaddr.sin6_family = AF_UNSPEC;
connect(fd, (struct sockaddr*)&sockaddr,sizeof(sockaddr));
nanosleep(&s, NULL);
}
}
How to make system choose port no for me on the connect() call in c below is my code where i have used 5000 as port no the problem is every time i have to keep on changing the port no because it is throwing exception as ?
listen: Address already in use
How to get rid of this i want to fix the port no without making change in future is it possible?
int main(void)
{
int sockfd = 0,n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
memset(recvBuff, '0' ,sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000); //how to skip Address already in use?
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
Check in IANA Port number Listing, pick the which is not assigned or registered a prior. In your case port number 5000 is a TCP port already registered and used for commplex-main.
Note: Do not choose ports between 0 - 1023 as they are used by system processes.
I created a TCP server program which binds, listen and accepting a connection from the specific ip address and port number.
During the first connection : Server is accepting a SYN packet from the client and sending an ACK back to the client. Later getting a ACK from the client. Finally Client is RST with the server.
During the second connection the client is sending a SYN packet to the slave but there is no ACK from the server.
I think there is no binding is possible during the second connection with the same ip address and port number.
Is it possible to bind with the SAME ip address and port number in the second connection ?
server :
SOCKET sock;
SOCKET fd;
uint16 port = 52428;
// I am also using non blocking mode
void CreateSocket()
{
struct sockaddr_in server, client; // creating a socket address structure: structure contains ip address and port number
WORD wVersionRequested;
WSADATA wsaData;
int len;
int iResult;
u_long iMode = 1;
printf("Initializing Winsock\n");
wVersionRequested = MAKEWORD (1, 1);
iResult = WSAStartup (wVersionRequested, &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
// create socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("Could not Create Socket\n");
//return 0;
}
printf("Socket Created\n");
iResult = ioctlsocket(sock, FIONBIO, &iMode);
if (iResult < 0)
printf("\n ioctl failed \n");
// create socket address of the server
memset( &server, 0, sizeof(server));
// IPv4 - connection
server.sin_family = AF_INET;
// accept connections from any ip adress
server.sin_addr.s_addr = htonl(INADDR_ANY);
// set port
server.sin_port = htons(52428);
//Binding between the socket and ip address
if(bind (sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
printf("Bind failed with error code: %d", WSAGetLastError());
}
//Listen to incoming connections
if(listen(sock, 10) == -1){
printf("Listen failed with error code: %d", WSAGetLastError());
}
printf("Server has been successfully set up - Waiting for incoming connections");
for(;;){
len = sizeof(client);
fd = accept(sock, (struct sockaddr*) &client, &len);
if (fd < 0){
printf("Accept failed");
closesocket(sock);
}
//echo(fd);
printf("\n Process incoming connection from (%s , %d)", inet_ntoa(client.sin_addr),ntohs(client.sin_port));
//closesocket(fd);
}
}
TCP connections are identified by four parameters:
Local IP
Local port
Remote IP
Remote port
The server normally uses the same Local IP and port for all its connections (e.g. an HTTP server listens on port 80 for all connection). Each connection from a client will have a different Remote IP and/or Remote port, and these resolve the ambiguity.
When the server closes all of its connected sockets, the TCB sticks around for several minutes in a TIME_WAIT state. This normally prevents a process from binding to the port, because you can't bind to a local IP/port that has any associated TCBs. If you want to restart the server and bind to the same port and address that it just used for connections, you need to use the SO_REUSEADDR socket option to get around this. See:
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?
for details of this.
I have simple server and client in UDP (WinSocks/C++).
I send datagram client -> server via sendto, and reply from server to client using the ip and port obtained from recvfrom function.
I found out that:
Every sendto from client is being sent from different port
When trying to reply from server Windows returns WSAECONNRESET (which mean that port is closed - http://support.microsoft.com/kb/263823)
How can I properly answer client from server (ie force port binding on client when sending using sendto?)
Edit: Adding some source code:
bool InitClient()
{
internal->sock = socket(PF_INET, SOCK_DGRAM, 0);
char8 yes = 1;
setsockopt(internal->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int32));
return internal->sock != -1;
}
void Send(const IpAddress & target, const uint16 port, const char8 * data, int32 size )
{
sockaddr_in trgt;
memset(&trgt, 0, sizeof(trgt));
trgt.sin_family = AF_INET;
trgt.sin_port = htons(port);
trgt.sin_addr.s_addr = target.GetRaw();
if(sendto(internal->sock, (const char8 *)data, size, 0, (PSOCKADDR)&trgt, sizeof(trgt)) == SOCKET_ERROR)
{
LOG("Network sending error: %d", WSAGetLastError());
}
}
Call the "bind" function to specify a local port to send from. Example of using port 4567 below. Make sure to check the return value from bind.Call this code after you create the socket.
sockaddr_in local = {};
local.family = AF_INET;
local.port = htons(4567);
local.addr = INADDR_ANY;
bind(internal->sock,(sockaddr*)&local, sizeof(local));
If you bind to port zero instead of 4567 then the os will pick a random port for you and use it for all subsequent send and receives. You can call getsockname to discover which port the os picked for you after calling bind.