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.
Related
Let's say we have a server that can accept multiple clients. First, it has to create a socket, then bind it with a port and an IP and finally listen to requests for connection from clients. After accept()ing a connection with a client, the server creates a new socket to communicate with the specific client. My question is whether or not the client is going to send its data to the same port it sent its initial request to, and if not how does it know where to send it?
A socket connection is uniquely identified by a tuple of [Protocol, Local IP, Local Port, Peer IP, Peer Port].
A TCP server creates a listening socket with a tuple of [TCP, Listen IP, Listen Port, 0, 0]. When a client requests to connect to a server, the network routes the request to the specified IP/Port. The receiving device then routes the request to a matching listening socket, performs a 3way handshake with the client, and puts it into a queue. Later, when accept() is called, it extracts the next pending client from the queue and returns a new socket identified with a tuple of [TCP, Listen IP, Listen Port, Client IP, Client Port]. Because of this, a single listening socket can accept multiple Clients from different Client IP/Port combinations.
A TCP client creates a connecting socket with a tuple of [TCP, Local IP, Local Port, 0, 0]. When the 3way handshake is complete, the socket's tuple is updated to [TCP, Local IP, Local Port, Server IP, Server Port]. Because of this, a Client can connect separate sockets to different Servers at differing Server IP/Port combinations.
All subsequent data exchanges use these tuples.
Data sent out from a Client's connecting socket will be sent to the associated Server IP/Port and stored in the buffer of the accepted Server socket whose tuple matches both the Client and Server.
Data sent out from a Server's listening socket will be ignored, since there is no associated Client.
Data sent out from an accepted Server socket will be sent to the associated Client IP/Port and stored in the buffer of the connected Client socket whose tuple matches the Client and Server.
Generally There is always a default port allotted for each kind of communication.Operating System may kept it open or close ,it can be checked .
Let's say for FTP connection, There is a separate port allotted for handshake,It don't matter how many new FTP connection are being requested, all new connection will go to that same port , Once handshake is completed data exchange is done via another port, Even if we don't specify port. If Network manager has Port List entries earlier it will request to the same port.
Example for SSH
if you request for
ssh -X <IP>
Even if you don't mention port , Your system know which port to request for and at server side there is always some port open who will be listening to your request and based on data you send while handshake it will continue listening or block you.
Bonus is you can open your custom port at server side who will be listening to your request. TCP implementation by default declare which port will be used for what kind of communication.
The client connects with a source IP and port to a server with a destination IP and port. After accept exactly the same IP and port on both sides are continued to be used for data exchange as for the establishment of the connection.
I want to exchange messages between client and server which are on two different machines. The two machines are directly connected by an Ethernet cable. I can successfully send and receive messages between client and server if they are both on the same machine. What should be the server address in order to have communication between the two machines?
serveraddr.sin_addr.s_addr = htonl( ???? );
I've tried running ifconfig on the server machine but just found the MAC address and no IP to assign in the code.
Both machines are running DHCP.
Have a look at the UDP wiki, as you can see, it requires an network layer. This is typically IP. You can set a static IP address to both devices and use these static IP address or you can set up a DHCP server on one of these machines to assign IP addresses automatically.
Directly connecting the machines with a cable creates a unique independent network (with only the two nodes).
Note that the cable will have to be a crossover cable.
DHCP probably won't help if neither node is a DHCP server.
As indicated in the answer by Marrten Arias, assign both the client, and the server a static ip address; perhaps something like this:
Server IP: 192.168.01.01
Client IP: 192.168.01.02
Mask (for both): 255.255.255.0
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.
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.
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.