I checked my code but I don't know why the program can't bind the socket.
I tried many ip and ports(even 127.0.0.1) but it still don't works...
Here is the code I'm using :
//error message
void error (const char *msg)
{
perror(msg);
exit(1);
}
int main ()
{
int sock, cli_sock, portno;
char buffer[1024];
char response[18432];
struct sockaddr_in serv_addr, cli_addr;
socklen_t cli_len;
//creating socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
error("Error opening socket");
bzero ((char *) &serv_addr, sizeof(serv_addr));
//giving port number
portno = 50005;
//giving ip address
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(portno);
//bind socket
if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != 0)
error("Binding failed.");
//listen
listen(sock, 5);
cli_len = sizeof(cli_addr);
//accept
cli_sock = accept(sock, (struct sockaddr *) &cli_addr, &cli_len);
if(cli_sock != 0)
error("Error on accepting");
}
(This is just the socket part of the server code and just for more info, my client version is for Windows and my server version is for Linux)
This is my output when I run the program :
Binding failed.: Cannot assign requested address
For TCP the setup for client and server were:
Server:
socket (create listening socket)
bind (listening socker to local address:port)
listen (make listening socket actually listen)
(accept loop header)
accept (have listening socket wait for incoming connections; returns accepted socket on succesful connection)
read/write (from/to accepted socket!)
shutdown (accepted socket; optional)
close (accepted socket)
(loop footer)
shutdown (listening socket; optional)
close (listening socket)
Client:
socket
bind (to local address:port, optional and uncommon)
connect (to remote address:port, those the server was bound to)
read/write
shutdown (optional)
close
Related
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.
I wrote a program to play tick tack toe across a network (or potentially the internet). I wrote this using C.
The program works just fine when I run the host and client on the same machine. I cannot, however, establish a connection when it is running on two different machines.
I'm using Ubuntu 18.04 LTS on both computers. I don't see why this would matter, but one is connected to the router via ethernet. The other is connected to the network wirelessly. ufw verbose shows that the firewall is inactive on both computers.
Things that I've already tried:
Adding server name to the host in /ect/hosts instead of typing
the ip address into the program argument (works both ways on local
machine, does not work either way across the network).
Adding firewall exception to the router firewall.
Port forwarding the port that I'm using (5001) on my router.
nmap to the ip of the computer running the host shows that port 5001/tcp is open with service "commplex-link"
Can telnet into the host from remote computer across the network.
void network_host(void) {
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
struct game *main_game = createboard();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("On opening socket ERROR: \n");
exit(1);
}
memset(&serv_addr, 0, sizeof serv_addr );
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof serv_addr ) < 0 ) {
perror("On socket binding ERROR: \n");
exit(1);
}
printf("Waiting for opponent . . .\n");
listen(sockfd, 1);
clilen = sizeof cli_addr;
memset(&cli_addr, 0, clilen);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("On accepting connection ERROR: \n");
exit(1);
}
printf("Opponent connected!\n");
while (main_game->play) {
printboard(main_game);
entermove(main_game, GAME_HOST, newsockfd);
checkwin(main_game);
}
}
void network_client(char *host_name) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
struct game *main_game = createboard();
portno = 5001;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Error opening socket");
exit(1);
}
server = gethostbyname(host_name);
if (server == NULL) {
fprintf(stderr, "Error, no such host.\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof serv_addr);
serv_addr.sin_family = AF_INET;
memcpy((char *)server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("Error connecting.\n");
exit(1);
}
while (main_game->play) {
printboard(main_game);
entermove(main_game, GAME_CLIENT, sockfd);
checkwin(main_game);
}
}
Since this program will work when connected to localhost, nmap shows the port open remotely, and I can telnet into the program remotely, I can't at all figure out where to go next.
It would seem to me that its not a coding error since it works locally, but since I can telnet into the program then it seems that it should't be a networking error.
I'm willing to backtrack through these steps (maybe some of them I've only done half right). But also willing to accept other possible ideas.
This line is where your problem is
memcpy((char *)server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
memcpy is defined as taking a destination, source and size...so you're copying things the wrong way around as server is where the address is. Swap things around and it should work just fine...
memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
You don't need to cast anything either as firstly those two arguments to memcpy are meant to be void * not char * and secondly, pointers convert to void * automatically
I am using sockets in order to synchronize several remote processes.
The idea is that a process creates a pthread which manages the server side, just like that:
void *listener(void * in) {
int sockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n = *((int *) in);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
int option = 1;
setsockopt(sockfd, SOL_SOCKET, (SO_REUSEPORT | SO_REUSEADDR), (char*) &option, sizeof (option));
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error("ERROR on binding");
if (listen(sockfd, n) < 0)
error("ERROR when listening");
clilen = sizeof (cli_addr);
int cnt = 0;
while (cnt < n) {
int newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
error("ERROR on accept");
}
cnt++;
}
close(sockfd);
return 0;
}
Meanwhile, the other processes would execute:
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(_managementHost); //managementHost);
if (server == NULL)
error("ERROR, no such host\n");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(PORT);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error("ERROR connection");
close(sockfd);
Now, the problem I have is when I have a lot of processes trying to connect at the same time to the server, some of them are throwing connection refused errors.
I guess that is because the accepts may not be ready... In fact, I have read that it could happen, but I have not found my specific case.
Could anyone shed light on the matter?
A possible solution that occurs to me, is to create a thread for each accept, but I would prefer to avoid it.
Thank you.
EDIT: corrected double initialization of socket in the server. Thanks to #Remy Lebeau.
Now, the problem I have is when I have a lot of processes trying to connect at the same time to the server, some of them are throwing connection refused errors.
A listening TCP socket has a backlog of pending connections. The 2nd parameter of listen() specifies how many connections are allowed to be in the backlog queue before they are accepted. If a new client tries to connect when the backlog is full, the client is refused. There is nothing the client or server can do about that. It is the client's responsibility to detect the error and re-connect at a later time.
Your listener() is accepting clients until it reaches a designated number of connections, but you are also using that same number for the listen backlog queue size. The number of active connections and the number of pending connections are two different things. If you are expecting a lot of clients to connect at the same time, you need a large backlog size to avoid the refusal errors. But that backlog should be sized proportional to the traffic you are expecting. If you have 1000 clients, but they connect only 20 at a time, you would set the backlog to, say, 25, not 1000.
Your listener() has some other logic bugs. It is calling socket() twice and saving the two sockets to the same sockfd variable, so it is leaking the first socket. You need to remove the second call to socket() (the one just before setsockopt()). You are also leaking the sockets that accept() returns. You need to close() an accepted socket after you are doing using it.
Just make your server concurrent by calling fork to spawn a child for each client. Easiest way to do it, IMO. Avoids threading and will stop the connection refused errors.
EDIT: You could also look into pre-forking your server. You'd have to research how you want to handle locking around accept, though (if you're locking at all).
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
I'm making a client program in C that has to deal with this situation:
1- server program receives udp datagram in port no 8080 sent by client with a port number X
2- server creates a new socket (TCP) in port number X
3- using this TCP socket, server reads a string sent by the client
(running on localhost)
I don't need to make the server program, it's already done. The points 1 and 2 are covered, but I've been a couple of days trying to work out the 3rd point and I'm not able to make it work ><
The code I've got for the client is this:
#define MYPORT 8080
int main(int argc, char *argv[ ]) {
int sockfd;
/* connector’s address information */
struct sockaddr_in their_addr;
struct hostent *he;
int numbytes;
int sockfd2, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc != 3) {
fprintf(stderr, "Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL) {
perror("Error obtaining the client. \n");
exit(1);
}
else printf("Client obtained\n");
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error creating UDP socket\n");
exit(1);
}
else printf("UDP Socket done\n");
their_addr.sin_family = AF_INET;
printf("Port: 8080\n");
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd2 < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
//sending port where the TCP socket will be associated
//server client connects correctly to this port
//and the code it's working fine in this point
if((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
{
perror("Client-sendto() error lol!");
exit(1);
}
//port is sent, now let's connect to the port by tcp and write the string
//not working properly from now on
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(atoi(argv[2]));
if (bind(sockfd2,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
listen(sockfd2, 5);
accept(sockfd2, 0, 0);
printf("accepted!\n");
//sending the string to the TCP Port...
if((numbytes = sendto(sockfd2, "hi", 2, 0, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr))) == -1)
{
printf("Client-sendto()-TCP error\n");
exit(1);
}
if (close(sockfd) != 0) printf("Client-sockfd-UDP closing is failed!\n");
else printf("Client-sockfd-UDP successfully closed!\n");
if (close(sockfd) != 0) printf("Client-sockfd2-TCP closing is failed!\n");
else printf("Client-sockfd2-TCP successfully closed!\n");
return 0;
}
The code works for the first two steps, but in the last step, it seems it's not connecting well with the TCP port, because my client program ends but my server program says that he receives null.
And of course I'm always sending ports > 1024
Thanks in advance, any help will be so appreciated.
listen(sockfd2, 5);
accept(sockfd2, 0, 0);
printf("accepted!\n");
I haven't read all your code, but the above (at least) is wrong. You absolutely need to retain the return value of accept: it's the socket you need to write to!
accept returns a file descriptor for the new TCP socket that has just been created for communicating with the "server" in your case. You need to use that as the file descriptor you write your string to.
(The sendto call just after that, apart from using the wrong socket, is a bit suspicious since the server will have no way to determine how much data to read/where the message stops. Passing a length of 3 (to include the \0 byte, would be a bit less suspicious.)