1

I'm new in C and have some problems with sockets. I'm creating a program which will be both server and client(I don't really know if this is acceptable but its for educational purposes). What i want program to do is: When the program(A) is run It should send some string to someone(program B) and then become server. In becoming server I mean it should listen and accept incoming connections. Here is my code of program A:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
perror(msg);
exit(1);
}

int main(int argc, char *argv[])
{
 int sockfd, newsockfd, portno, number;
 socklen_t clilen;
 char buffer[256];
 struct sockaddr_in serv_addr, cli_addr;
 int n;
 if (argc < 2) {
     fprintf(stderr,"ERROR, no port provided\n");
     exit(1);
 }
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd < 0) 
    error("ERROR opening socket");
 bzero((char *) &serv_addr, sizeof(serv_addr));
 portno = atoi(argv[1]);



 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = 0;
 serv_addr.sin_port = htons(portno);


 connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
 number = write(sockfd,"Hey!",strlen("Hey!"));



 if (bind(sockfd, (struct sockaddr *) &serv_addr,
          sizeof(serv_addr)) < 0) 
          error("ERROR on binding");

 listen(sockfd,5);
 clilen = sizeof(cli_addr);
 sockfd = accept(sockfd, 
             (struct sockaddr *) &cli_addr, 
             &clilen);
 if (sockfd < 0) 
      error("ERROR on accept");
 bzero(buffer,256);
 n = read(sockfd,buffer,255);
 if (n < 0) error("ERROR reading from socket");
 printf("Here is the message: %s\n",buffer);
 n = write(sockfd,"I got your message",18);
 if (n < 0) error("ERROR writing to socket");
 close(sockfd);

 return 0; 
}

and the code for program B:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
perror(msg);
exit(1);
}

int main(int argc, char *argv[])
{
 int sockfd, newsockfd, portno;
 socklen_t clilen;
 char buffer[256];
 struct sockaddr_in serv_addr, cli_addr;
 int n;
 if (argc < 2) {
     fprintf(stderr,"ERROR, no port provided\n");
     exit(1);
 }
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd < 0) 
    error("ERROR opening socket");
 bzero((char *) &serv_addr, sizeof(serv_addr));
 portno = atoi(argv[1]);



 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = 0;
 serv_addr.sin_port = htons(portno);


 if (bind(sockfd, (struct sockaddr *) &serv_addr,
          sizeof(serv_addr)) < 0) 
          error("ERROR on binding");
 listen(sockfd,5);
 clilen = sizeof(cli_addr);
 sockfd = accept(sockfd, 
             (struct sockaddr *) &cli_addr, 
             &clilen);
 if (sockfd < 0) 
      error("ERROR on accept");
 bzero(buffer,256);
 n = read(sockfd,buffer,255);
 if (n < 0) error("ERROR reading from socket");
 printf("Here is the message: %s\n",buffer);
 n = write(sockfd,"I got your message",18);
 if (n < 0) error("ERROR writing to socket");
 close(sockfd);

 return 0; 
}

When I first run program B and the A. The string Hey is received but then program A crashes and gives error ERROR on binding: Invalid argument. This error comes up from bind function but i can't figure out why? Thanks.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
Ojs
  • 924
  • 1
  • 12
  • 26
  • 1
    A cursory read of `man bind` suggests `EINVAL The socket is already bound to an address.`, so you probably want to `close()`, then `socket()` the `sockfd` before `bind()`ing. – EOF Jul 24 '15 at 11:43

3 Answers3

0

When you want your code to work as both Server and Client then it is called as TCP Proxy. I hope this link will help you in implementing that.

A TCP proxy is a server that acts as an intermediary between a client and another server. Client establish connections to the TCP proxy server, which then establishes a connection to the destination server.

Amol Saindane
  • 1,568
  • 10
  • 19
  • What I'm trying to do is start connection from program A. And I don't understand why error occurred when sockfd didn't change. – Ojs Jul 24 '15 at 11:53
0

This is broken by design! You have to decide which program is the server side (calling bind()) and which one is the client side (calling connect()). This has nothing to do with reading and writing, the connection is bi-directional. But on a side note, a decent server should be capable of accept()ing multiple connections ... traditionally this is done by forking, there are better ways depending on your scenario.

0

Well there are many reasons why the bind can fail.

First, the socket is already connected so it is already bound to a local address even if you did not specified it. When you called connect, the system automatically bound the socket to a local free address. So the bind call should fail. bind man page gives this possible error

[EINVAL] The socket is already bound to an address, and the protocol does not support binding to a new address...

And that's not all. Program B is already listening on same address. So even is you closed and reopened the socket, the bind call will still fail with :

[EADDRINUSE] The specified address is already in use.

if you do not wait that B closes its own socket

Here the problem is not with C programming but with TCP/IP network. A socket in domain AF_INET is a network bidirectionnal connection between 2 endpoints consisting of an IP address and a port number. One single pair (address, port) cannot be opened more than once at the same time. Because as this address is used to know where packets should be delivered, if must be unique.

So you should :

  • close and reopen the socket
  • wait some time (one second should be enough) for B to close its socket before binding to server address

Last but not least :

Is is wrong and dangerous to close a socket immediately after writing something to it : depending on network configuration, size of messages, etc. the close can destroy part of last writes that could have not been sent. As you use short messages on loopback interface, I do not think it happens here. But if you want to master socket usage, you could try graceful shutdown

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252