Cannot send information between multiple clients connected to a server - c

I have multiple clients connected to a server. Each time the server sends a string which contains the IP and address of client 1 to client 2, client 2 connects to client 1 and sends it a message.
Server and clients are local; they have same IP but different listening ports.
I get the following error: Transport endpoint is already connected.
After debugging, I think it is because of the same IP address, although i don't understand why it doesn't connect through the port. Client 2 gets the correct port of client 1.
(note: i omitted the error handling)
Here's the code:
sockfd = socket(AF_INET, SOCK_STREAM,0); //the one for the server
sockfd2 = socket(AF_INET, SOCK_STREAM,0); //the one for the client
//creating client
client.sin_family = AF_INET;
client.sin_port = htons(atoi(argv[3])); // the port is read from command line
client.sin_addr.s_addr = INADDR_ANY;
//bind
int b = bind(sockfd2, (struct sockaddr *) &client, sizeof(struct sockaddr));
//listen
listen(sockfd2,1); //only 1 client can connect to this one!
//creating server
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[5])); // the port is read from command line
inet_aton(argv[4], &serv_addr.sin_addr);
connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
while(1){
... // the client connects to the server and gets the string
destination.sin_family = AF_INET;
destination.sin_addr.s_addr= inet_addr(address);
destination.sin_port = htons(atoi(port));
//this line gives the error
if(connect(sockfd2,(struct sockaddr*)&destination, sizeof(destination)<0)
error("Error connecting");
//the sending
n = send(sockfd2, message, strlen(message), 0);
if(n<0)
error("Error sending");
....
}

sockfd2 which you try to connect() is already bound, and assigned a role (by means of listen) to be a server socket. Basically the only valid operation it can do is to accept() an incoming connection.

Related

Invalid argument to connect()

I'm trying to write code to setup a client socket that can send/receive messages from a server. Here's what I have:
// Create the socket
int s = socket(AF_INET, SOCK_STREAM, 0); // TODO: error checking
// Setup the client and server addresses
struct sockaddr_in cli_addr;
memset(&cli_addr, 0, sizeof(cli_addr));
cli_addr.sin_family = AF_INET;
cli_addr.sin_port = htons(7654);
cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(11111);
serv_addr.sin_addr.s_addr = inet_addr("XXX.XXX.XXX.XXX");
// Bind the socket to the client address (so we can receive messsages)
if (bind(s, (struct sockaddr*)&cli_addr, sizeof(cli_addr)) == -1) {
perror("bind failed");
exit(errno);
}
// Connect the socket to the server address (so we can send messages)
if (connect(s, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
perror("connect failed");
exit(errno);
}
When I run this, I'm getting the error connect failed: Invalid argument. I don't see what I'm doing incorrectly here, though.
cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
...
serv_addr.sin_addr.s_addr = inet_addr("XXX.XXX.XXX.XXX");
You'll bind the socket to localhost (127.0.0.1) but then you connect to an address which likely is not localhost. There is no way such a TCP with a fully internal IP address (i.e. not accessible from outside the machine) to an IP address of a different system can be created, hence "Invalid argument".
It is unclear what you are trying to achieve with the bind in the first place so it might be the best to just remove it. In this case it will automatically pick a local IP and port which can be used in a connection to the given destination IP.

c - connect() does not return

I'm trying to build a c client that sends an html request message to a website, and then reads the response. Unfortunately, my connect() statement does not return.
Yes, I have seen this answer: connect() does not return
However, I do not want to set the socket to non-blocking, and then keep doing select() until I get a response, as I am only dealing with one request at a time.
int main() {
struct hostent *hp;
struct sockaddr_in serveraddr;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
hp = gethostbyname("firefox.com"));
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0], (char *)&serveraddr.sin_addr.s_addr, hp->h_length);
serveraddr.sin_port = htons(8080); // works up till here
connect(mySocket, (SA *) &serveraddr, sizeof(serveraddr)); // never returns
return 0;
}
Am I connecting correctly? I've gotten rid of the error checking in the above code.
Here is the output of "lsof -Pnl +M -i4" in terminal
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
proxy 8321 1000 3u IPv4 51542 0t0 TCP 10.0.2.15:42708->63.245.213.17:8080 (SYN_SENT)
Could this be a firewall issue? If so, how do I resolve it?
I should've been on port 80, not 8080, in the line:
serveraddr.sin_port = htons(8080); // no
serveraddr.sin_port = htons(80); // yes
Thanks for your help guys.

C Server connect to Client

I'm trying to make a Server/Client with push notifications.
First of all the Client connects with Server and then Server saves IP address and port of the client. At some point server needs to connect with client to send a notification.
This is how Server saves Client IP address and port after the accept of the first connection:
char client_ip[INET_ADDRSTRLEN];
int port_c;
// Socket, ..., bind, listen, accept
// Gets Client IP address
struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&cli_addr;
struct in_addr ipAddr = pV4Addr->sin_addr;
inet_ntop( AF_INET, &ipAddr, client_ip, INET_ADDRSTRLEN );
printf("Client ip: %s\n", client_ip);
// Gets Client Port Number
port_c = (int) ntohs(cli_addr.sin_port);
printf("Client port is: %d\n", (int) ntohs(cli_addr.sin_port));
// [ ... ]
// Time to send notification to client
bzero((char *) &cli_addr, sizeof(cli_addr));
// Setting IP address and port
cli_addr.sin_family = AF_INET;
bcopy(client_ip, (char *)&cli_addr.sin_addr.s_addr, strlen(client_ip));
cli_addr.sin_port = htons(port_c);
// Create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// Bind socket to the local address
if(bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
error("Error bind");
if (connect(sockfd, (struct sockaddr *)&cli_addr, sizeof(cli_addr)) < 0)
error("ERROR connecting");
I get bind error: Can't assign requested address.
And I am not sure how to code Client after the first connection. It would be listening and accepting the connection but if I do in the Client's code
cli_addr.sin_family = AF_INET;
cli_addr.sin_addr.s_addr = INADDR_ANY;
cli_addr.sin_port = htons(port_client);
Will the IP address be the same as the first connection?
If someone has another solution or better, please share it.
You are trying to bind the server socket to a client IP. That cannot work. You can only bind a socket to a local address. You must use bind for incomming connections, not for outgoing ones.
If you want your server to respond to a request from the client, simply use the socket returned by accept(), then send() using this socket.
You server code should look like this:
SOCKET sock_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sock_local_addr;
memset(&sock_local_addr, 0, sizeof(sock_local_addr));
sock_local_addr.sin_family = AF_INET;
sock_local_addr.sin_port = htons(SERVER_PORT);
sock_local_addr.sin_addr.s_addr = INADDR_ANY;
bind(sock_server, (const struct sockaddr *)&sock_local_addr, sizeof(sock_local_addr)); // bind server socket to any network interface of the server
listen(sock_server, 10);
struct sockaddr_in client_addr;
SOCKLEN_T client_addr_size = sizeof(client_addr);
SOCKET sock_client = accept(sock_server, (struct sockaddr *)&client_addr, &client_addr_size); // accept incomming connection; this will block until a client connects
recv_size = recv(sock_client, buf_in, sizeof(buf_in), 0); // receive data from client
send(sock_client, buf_out, sizeof(buf_out), 0); // send data back to client (buf_out is buffer containing the data to be sent)
shutdown(sock_client, SHUT_RDWR); // shutdown connection with client

UDP Client shows 'UDP Connected' while no UDP Server running on localhost

What is wrong with the following function ??
It should throw an error as I have no UDP server running on localhost.
int openUdpSocket(int port) {
int sock,sin_size;
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
struct hostent *host;
host= (struct hostent *) gethostbyname((char *)"127.0.0.1");
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
sin_size = sizeof(struct sockaddr);
Now the Following part causing trouble : -
int error = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(error < 0){
printf("Connection error\n");
exit(-1);
}
if (verbose)
printf("UDP connected\n");
return sock;
}
Output:
udit#mylaptop:~/Desktop/benchmark$ ./a.out
UDP connected
Note that I have created a similar function for TCP and the same thing is working fine with TCP that means when no TCP Server running it shows connection error and when TCP Server running then TCP Connected
The UDP Client mentioned above needs to receive response in form of some status codes in future. SO, Do I need to use bind() function here ??
You need to lookup what connect() does for a SOCK_DGRAM socket. It doesn't imply the existence of a peer. It only establishes an inbound and outbound IP address filter. See man 2 connect.
for UDP communication you need to use Sendto and Receivefrom functions,
bind and connect are not required for UDP communication.
try to search about this two functions and use them. :)

C: Issues binding an open port to a socket

I'm working on an assignment that deals with binding an available port to a TCP socket. Initially, when I wrote my server code, I set a predefined port for the system to listen on, and this worked perfectly. However, upon converting my code to bind to an open port and print the port being used, I am unable to connect to the server via telnet.
I came across another interesting anomaly when I converted my code back to using a predefined port. Once again, the server worked as expected on the predefined port, however, the port that it reported to be using was different than what I had assigned it.
This first code snippet creates a socket and uses a predefined port (32000).
/*Create TCP socket with a predefined port*/
listener = socket(AF_INET, SOCK_STREAM, 0);
if(listener == -1) {
perror("Create socket");
exit(1);
}/*End if*/
bzero(&servaddr, sizeof(servaddr));/*Set serraddr to 0's*/
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*Any of this host's interfaces is OK.*/
servaddr.sin_port = htons(32000);
bind(listener, (struct sockaddr *)&servaddr, sizeof(servaddr));
length = sizeof(servaddr);
/*getsockname(listener, (struct sockaddr *)&servaddr, &length);/*Find out port number*/
printf("RSTREAM:: assigned port number %d\n", servaddr.sin_port);
This second code snippet uses an available port. I tried setting servaddr.sin_port to 0 because I read that doing so signifies that the system is to provide an available port. I also tried commenting this line out just for the heck of it, but the results were the same.
/*Create TCP socket with an open port*/
listener = socket(AF_INET, SOCK_STREAM, 0);
if(listener == -1) {
perror("Create socket");
exit(1);
}/*End if*/
bzero(&servaddr, sizeof(servaddr));/*Set serraddr to 0's*/
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*Any of this host's interfaces is OK.*/
servaddr.sin_port = htons(0);/*bind() will provide unique port.*/
bind(listener, (struct sockaddr *)&servaddr, sizeof(servaddr));
length = sizeof(servaddr);
getsockname(listener, (struct sockaddr *)&servaddr, &length);/*Find out port number*/
printf("RSTREAM:: assigned port number %d\n", servaddr.sin_port);
You need to print the converted port number, i.e. you need to do ntohs(3):
printf("RSTREAM:: assigned port number %d\n", ntohs(servaddr.sin_port));

Resources