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.
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 :
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