Reputation: 157
I have a socket app written in c and I am executing on linux, but when I execute the server (./server), I get the following error:
connection failed, connection refused.
Here is the code:
server.c
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#define DEFAULT_PORT 8080
void error(char* message){
perror(message);
exit(EXIT_FAILURE);
}
void handler_client(void){
}
int main(int argc , char **argv[]){
int server_fd;
int new_socket;
int valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello, I'm server";
if((server_fd = socket(AF_INET, SOCK_STREAM , 0)) == 0){
error("socket failed");
}
if(setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT , &opt , sizeof(opt))){
error("setsockertopt");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(DEFAULT_PORT);
if(bind(server_fd , (struct sockaddr *)&address, sizeof(address) ) < 0){
error("bind failure");
}
if(listen(server_fd , 3) < 0){
error("listen");
}
if((new_socket = accept(server_fd , (struct sockaddr *)&address , (socklen_t *)&addrlen)) < 0){
error("accept");
}
valread = read( new_socket , buffer , 1024);
printf(" message from client : %s \n",buffer);
send(new_socket , hello , strlen(hello) , 0);
printf("Hello message sent \n");
return 0;
}
client.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define DEFAULT_PORT 8080
#define BUFFER_SIZE 1024
void error(char* message){
perror(message);
exit(EXIT_FAILURE);
}
int main(int argc , char** argv){
struct sockaddr_in address;
int sock = 0;
int valread;
struct sockaddr_in serv_addr;
char message[BUFFER_SIZE] = {0};
char buffer[BUFFER_SIZE] = {0};
if((sock = socket(AF_INET , SOCK_STREAM , 0)) < 0){
error("Sockert Creation fails");
}
memset(&serv_addr , '0' , sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(DEFAULT_PORT);
if(inet_pton(AF_INET , "127.0.0.1" , &serv_addr.sin_addr) <= 0){
error("Invalid address / Address not supported");
}
if(connect(sock , (struct sockaddr *)&serv_addr , sizeof(serv_addr) ) < 0){
error("connection failed");
}
printf("enter your message : ");
fgets(message , BUFFER_SIZE-1 , stdin);
send(sock , message , strlen(message) , 0);
printf("Hello message sent\n");
valread = read(sock , buffer , BUFFER_SIZE);
printf("response from buffer : %s\n",buffer);
return 0;
}
Upvotes: 1
Views: 9619
Reputation: 595377
A "connection refused" error means you are trying to connection to a server IP:port that is either:
not open for listening
has too many pending client connections in its backlog
blocked by a firewall/router/antivirus.
There is no way on the client side to differentiate which condition is causing the error. All it can do is try again later, and give up after awhile.
Since your client is trying to connection to 127.0.0.1
, the client and server MUST be run on the same machine. You will not be able to connect across machine boundaries, and that includes VM boundaries between host/client systems.
That being said, I see a number of mistakes in your code, but none that are causing the connection error.
Server side:
socket()
returns -1 on error, not 0.
//if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
you can't set multiple socket options at a time with setsockopt()
, you must set them individually with separate calls to setsockopt()
.
//setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(server_fd , SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
Client side:
you are filling serv_addr
with '0'
characters instead of 0
bytes.
//memset(&serv_addr , '0' , sizeof(serv_addr));
memset(&serv_addr, 0, sizeof(serv_addr));
On both sides, you are not doing any error handling on send()
. But more importantly, you are not including the message's null terminator in the send, so the peer has no way of knowing when the end of the message is reached. TCP is a streaming transport, so you need to frame your messages in your data protocol. Send the message's length before sending the message itself. Or send a unique terminator after the message. The peer can then read the length before reading the message, or read until the terminator is reached.
Both send()
and read()
return how many bytes were actually sent/received, which can be (and frequently is) fewer bytes than requested. You need to call them in a loop to make sure that you send/receive everything you are expecting.
Also, read()
does not return a null-terminated string, but your use of printf()
expects one. Check valread
for error, and only if read()
was successful then pass valread
to printf()
as an input parameter so it knows how much data is actually in the buffer
:
printf("message from client : %.*s\n", valread, buffer);
printf("response from buffer : %.*s\n", valread, buffer);
Upvotes: 3