I create a server at port 1234 of localhost. In the client code, I initiated a struct sockaddr_in server_addr and filled it with the server's IP address and port number. When I try to connect a client to the server, I get "Address already in use":
bind(client_sockfd, server_addr, sizeof server_addr)
So the OS thinks that I was trying to create another server socket with the same address and port number. In this case, how can I tell the OS that server_addr is the other endpoint I want to connect to and that it finds another port number for the client's socket?
You need to use bind() only for the server and in the client use
int connect(int socket, const struct sockaddr *address,
socklen_t address_len);.
See this tutorial for information about sockets in Linux:
http://www.linuxhowtos.org/C_C++/socket.htm
you use connect(client_sockfd, server_addr, sizeof(..)) to tell OS that my client socket should connect to this server address.
If it is UDP socket, you can also use sendto(client_sockfd, ... server_addr) call to specify that the packet should go to this server address.
Related
I'm writing a simple server/client program in C. I'm trying to open a port on an IP that can be accessed from anywhere. Currently, my server does not work for anything but 127.0.0.1 (local machine) and 0.0.0.0 (I don't know). I've specified the IP_TRANSPARENT option and all that but the client still fails at connect.
server:
// definitions, everything
struct addrinfo hints, *res;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("192.168.1.1","4001",&hints,&res);
sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
setsockopt(sockfd,IPPROTO_IP,IP_TRANSPARENT,(void*)&sockopt,sizeof(sockopt));
bind(sockfd,res->ai_addr,res->ai_addrlen);
listen(sockfd,0);
addr_size = sizeof(ext_addr);
extfd = accept(sockfd,(struct sockaddr *)&ext_addr,&addr_size);
write(extfd,"Success",7);
// cleanup
client:
// definitions, everything
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET,SOCK_STREAM,0);
setsockopt(sockfd,IPPROTO_IP,IP_TRANSPARENT,(void*)&sockopt,sizeof(sockopt));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(4001);
inet_pton(AF_INET,"192.168.1.1",&serv_addr.sin_addr);
connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); // fails here
read(sockfd,rcvBuf,sizeof(rcvBuf)-1);
// clean up
What's my issue? I have taken out the error checking for the sake of convenience. The server runs fine, I am sure of that. The client runs fine with 127.0.0.1.
Typically, you cannot bind() to an IP that does not belong to the local machine. However, per the IP_TRANSPARENT documentation:
IP_TRANSPARENT (since Linux 2.6.24)
Setting this boolean option enables transparent proxying on this socket. This socket option allows the calling application to bind to a nonlocal IP address and operate both as a client and a server with the foreign address as the local endpoint. NOTE: this requires that routing be set up in a way that packets going to the foreign address are routed through the TProxy box (i.e., the system hosting the application that employs the IP_TRANSPARENT socket option). Enabling this socket option requires superuser privileges (the CAP_NET_ADMIN capability).
TProxy redirection with the iptables TPROXY target also requires that this option be set on the redirected socket.
Have you configured the necessary proxying on your network to facilitate IP_TRANSPARENT?
Let's ignore IP_TRANSPARENT for a moment, pretend it does not exist, as it is not commonly used.
127.0.0.1 is the IPv4 loopback address. If you bind your server to this, only local IPv4 clients that connect to 127.0.0.1 will be able to connect.
0.0.0.0 is an IPv4 wildcard address. If you bind your server to this, the socket will listen on all local IPv4 addresses. Any client on the local machine or network can connect to any IPv4 address that belongs to the server machine.
192.168.1.1 is a specific IPv4 address. If you bind your server to this, the socket will listen on that IPv4 address only. Any client on the local machine or network can connect to only that IPv4 address.
If your client and server are on the same machine, the client can connect to any local IP that the server is bound to.
If your client and server are not on the same machine, bur are on the same network, the client can connect to the server if the server is bound to an IP that is accessible to that network. That means binding to 0.0.0.0 or 192.168.1.1, and then connecting to 192.168.1.1.
If your client and server are not on the same network, the client can connect to the server only if the server is behind a router with a public IP. The server must be bound to a local network IP that is accessible to the router, and the router must be configured to forward inbound connections on a given port on its public IP to the server's internal IP. That means binding the server to 0.0.0.0 or 192.168.1.1, forwarding connections to the server's internal IP, and then connecting to the router's public IP.
I have a server:
./server portNumber
I have a client:
./client serverIpAddress
I have only server Ip Address in the client. I want to connect to Server socket. But every time Server Port Number is different. How Can I connect to server socket with BSD Socket in the client? Is it impossible? Do I have to know server port number?
Simple Usage BSD Socket:
int socket_desc;
struct sockaddr_in server;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
server.sin_addr.s_addr = inet_addr(ipAddress);
server.sin_family = AF_INET;
server.sin_port = htons( ThisIsServerPortNumber );
//Connect to remote server
if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
Pick a port number between 49152 and 65535 for development. If your idea is successful, you'll want to register a port number between 1024 and 49151. Port numbers from 0 to 1023 are well-known ports, e.g. port 80 is for HTTP servers.
The TCP Port Service Multiplexer protocol was intended to allow discovery of port numbers for TCP servers, but it's seldom used due to security concerns.
The bind(2) system call is used to select a port number in a server. It has to be called before the listen(2) system call and after the socket(2) call.
It allows to specify, not only the port number the server is going to listen for connections, but also the ip address in case the host has several interfaces and you want only to accept connections in one of the interfaces.
But every time Server Port Number is different. How Can I connect to
server socket with BSD Socket in the client? … Do I have to know
server port number?
Yes, you have to know it. Think: There can be many different server programs running on the server host, bound to many different ports. A client computer has no simple insight into the server host to see to which port the desired server program is bound. Thus, it is usual to use a preassigned port number in the server as well as in the client.
How can I get the ip address of the client of which my server is connected to?
Here is how I accept incoming clients:
newsockfd = accept(sockfd, (struct sockaddr*)&clt_addr, &addrlen);
I tried the following:
printf("ip is: %s\n", inet_ntoa(clt_addr.sin_addr));
But I am getting 127.0.0.1 which is not my ip address. Could it have something to do with me using localhost to test my client and server?
Could it have something to do with me using localhost to test my client and server?
Yes. If you connect to a server on localhost the client will also be localhost. This connection is not happening over the Internet, there is no network hardware involved, the client packets will come from localhost. This is known as loopback and occurs entirely in software.
If the client were to connect to the server using the server's external IP address it will have to do a connection via external routing and thus require a routable IP address. For example, I can connect to a server on localhost, but I cannot using my routable IP address because my router blocks incoming connections.
Can I create 2 UDP sockets on the same client machine (but will be used in 2 different threads) to connect to a server? One thread sends datagrams to and the other receives datagrams from the server. Are these the correct steps:
create a sockaddr_in for the server's given address and UDP port.
create a socket and connect it to the server's sockaddr_in. This
is the sending socket.
Create another socket, assign a port and
sent the port number to the server.
Thank you.
My server is creating a IPV6 socket.
On client I am creating a IPV4 socket.
Now, In the connect API on client side I am passing the socket descriptor of IPV4 and IPV6 address structure.
INET_connect( sock,(SocketAddress *)in6_addr,(int)sizeof( sockaddr_in6 ) ) == 0 )
where
struct sockaddr_in6 in6_addr;
I am getting error in connection. Is it due to this or some other reason ?
Please note that my server is IPV6(having an IPV6 address)
You must use an IPV6 socket to connect to an IPV6 address, or use a tunneling service which will translate traffic from IPV4 addresses to and from IPV6 addresses.
On client I am creating a IPV4 socket
Why? Don't do that. If your client program creates an AF_INET socket (or is running on ip4-only OS) then there is nothing you can do on the client side to make such connection happen.
If you just have to do so - then it is the server that should be adapted to handle IPv4 clients.
Server might be able to accept a connection request from ip4 client - but it can only happen if server side disables IPV6_V6ONLY socket option and, obviously, if server's OS allows that. In this case ip6 server will see the ip4 client via ipv4-mapped ipv6 address.