Here's the code:
if (!isconnected){ printf("Connecting to %s\n",inet_ntoa(outlink_addr.sin_addr)); if (connect(outsock, (struct sockaddr *)&outlink_addr,sizeof(struct sockaddr)) == -1) { perror("connect"); //close(outsock); //exit(1); }else{ printf("Connected to %s (%d)\n",inet_ntoa(outlink_addr.sin_addr),outsock); FD_SET(outsock, &master); // add to master set if (outsock > fdmax) { // keep track of the maximum outsock = newfd; } isconnected = 1; } }
And the output:
Unreal2Hybrid: new connection from 192.168.0.2 on socket 4
Connecting to 63.110.124.45
connect: Transport endpoint is already connected
I can't figure out why it can't reconnect (it connects once, and only once, do I need to reset the struct or something?).
And yes, this is using select, a modified select thingy from Beej. If you want I can post the entire code...
Theres a nice option called something like: SO_REUSEADDR.
Most probably the problem is in the bind, not the connect.
It is an operative system issue. If you don't close the socket correctly (in example, press CTRL-C to end the program), the port is never freed. In Linux there used to be a delay of around 30 seconds-1 minute until the OS freed the socket and you were able to bind it again.
Heres a little function I found and modified:
| 1 | int make_socket (unsigned short port) |
| 2 | { |
| 3 | int sock, yes = 1; |
| 4 | struct sockaddr_in name; |
| 5 | |
| 6 | /* Create the socket. */ |
| 7 | sock = socket (PF_INET, SOCK_STREAM, 0); |
| 8 | if (sock < 0) { |
| 9 | /*char *buf = calloc(1, 256); |
| 10 | if(!buf) |
| 11 | exit (EXIT_FAILURE); |
| 12 | */ |
| 13 | log_printf(global_log, LOG_LEVEL_FATAL, "socket: failed..."/*, strerror_r(errno, buf, 256)*/); |
| 14 | //free(buf); |
| 15 | exit (EXIT_FAILURE); |
| 16 | } |
| 17 | if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(const char *)&yes,sizeof(int)) == -1) { |
| 18 | /*char *buf = calloc(1, 256); |
| 19 | if(!buf) |
| 20 | exit (EXIT_FAILURE); |
| 21 | */ |
| 22 | log_printf(global_log, LOG_LEVEL_FATAL, "setsockopt: failed..."/*, strerror_r(errno, buf, 256)*/); |
| 23 | //free(buf); |
| 24 | exit (EXIT_FAILURE); |
| 25 | } |
| 26 | |
| 27 | /* Give the socket a name. */ |
| 28 | name.sin_family = AF_INET; |
| 29 | name.sin_port = htons (port); |
| 30 | name.sin_addr.s_addr = htonl (INADDR_ANY); |
| 31 | if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { |
| 32 | char *buf = calloc(1, 256); |
| 33 | if(!buf) |
| 34 | exit (EXIT_FAILURE); |
| 35 | |
| 36 | log_printf(global_log, LOG_LEVEL_FATAL, "bind: failed..."/*, strerror_r(errno, buf, 256)*/); |
| 37 | //free(buf); |
| 38 | exit (EXIT_FAILURE); |
| 39 | } |
| 40 | |
| 41 | log_printf(global_log, LOG_LEVEL_NOTE, "Succsessfully bound to port: %i", port); |
| 42 | |
| 43 | return sock; |
| 44 | } |
The log_* functions are mine, not libc or anything... Oh, and note, this is for a server style port IIRC.
How is the server code? It is listening for more connections?
The server listens for connections, and if it find that when a client connects that it's not connected to another server, then it connects to it...
I want it to reconnect to that socket if the connection is lost.
EDIT: Why do you have to bind when connecting to something else?
The code is old, you don't want to open a new port everytime you connect to something 
You should show the server code, though. The client should not have problem no matter how many they are.
I edited it so that it recalled the socket thingy...
| 1 | if (!isconnected){ |
| 2 | printf("Connecting to %s (cached)\n",inet_ntoa(outlink_addr.sin_addr)); |
| 3 | if (connect(outsock, (struct sockaddr *)&outlink_addr,sizeof(struct sockaddr)) == -1) { |
| 4 | perror("connect"); |
| 5 | if ((outlink=gethostbyname("palace.morphforest.com")) == NULL){ |
| 6 | perror("gethostbyname"); |
| 7 | exit(1); |
| 8 | } |
| 9 | if ((outsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { |
| 10 | perror("socket"); |
| 11 | exit(1); |
| 12 | } |
| 13 | outlink_addr.sin_family = AF_INET; // host byte order |
| 14 | outlink_addr.sin_port = htons(7029); // short, network byte order |
| 15 | outlink_addr.sin_addr = *((struct in_addr *)outlink->h_addr); |
| 16 | memset(&(outlink_addr.sin_zero), '\0', 8); // zero the rest of the |
| 17 | |
| 18 | // lose the pesky "address already in use" error message |
| 19 | if (setsockopt(outsock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { |
| 20 | perror("setsockopt"); |
| 21 | exit(1); |
| 22 | } |
| 23 | printf("Connecting to %s (last attempt)\n",inet_ntoa(outlink_addr.sin_addr)); |
| 24 | if (connect(outsock, (struct sockaddr *)&outlink_addr,sizeof(struct sockaddr)) == -1) { |
| 25 | perror("connect"); |
| 26 | exit(1); |
| 27 | }else{ |
| 28 | printf("Connected to %s (%d)\n",inet_ntoa(outlink_addr.sin_addr),outsock); |
| 29 | FD_SET(outsock, &master); // add to master set |
| 30 | if (outsock > fdmax) { // keep track of the maximum |
| 31 | outsock = newfd; |
| 32 | } |
| 33 | isconnected = 1; |
| 34 | } |
| 35 | //close(outsock); |
| 36 | //exit(1); |
| 37 | }else{ |
| 38 | printf("Connected to %s (%d)\n",inet_ntoa(outlink_addr.sin_addr),outsock); |
| 39 | FD_SET(outsock, &master); // add to master set |
| 40 | if (outsock > fdmax) { // keep track of the maximum |
| 41 | outsock = newfd; |
| 42 | } |
| 43 | isconnected = 1; |
| 44 | } |
| 45 | } |
Hmm... close the old socket before creating a new one. And you meant reusing a socket to connect? Ah... I misunderstood, sorry.
The old one is automatically closed on error or disconnect.
This seems to work though.
Hmm... really? It frees the descriptor? Geez... it must have changed since the last time I did some real network programming then...
Yeah, it reuses file descriptors, the lowest one free (hense if you close stout and open a new file, all stout will go to the file...
That's the logic between piping stout, you close it then you ddup it or whatever...