C socket successfully accept() but fails on recv() - c

I am trying to implement a server which accepts 2 connections one after another each of them sending data. My client-side can connect and fwrite successfully whereas my server-side connects successfully but fails to recv() anything. I have tried many things on the net but I could not resolve this. Why would recv() fail in this code after succesfully accepting and connecting on the socket?
Code of Server part —— Successful on accept() but fail on recv()
char** get_host_ip(){
char** arr = malloc(3* sizeof(char*));
int x;
for(x=0; x<3;x++){
arr[x] = malloc(256 *sizeof(char));
}
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
fd_set fdset;
struct timeval tv;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
//fcntl(socket_desc, F_SETFL, O_NONBLOCK);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
int reuse = 1;
if (setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEADDR) failed");
}
if(setsockopt(socket_desc, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEPORT) failed");
}
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
char* err = "Error on binding\r\n";
printf("%s\r\n",err);
}
puts("bind done");
//Listen
listen(socket_desc , 20);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
int k;
for(k=0; k<2; k++){
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if(client_sock < 0){
puts("Accept failed\r\n");
exit(0);
}
else{
puts("Accept succeeded");
}
if(k == 0) {
char* host_ip = inet_ntoa(client.sin_addr);
printf("IP address is: %s\n", inet_ntoa(client.sin_addr));
printf("port is: %d\n", (int) ntohs(client.sin_port));
strcpy(arr[k],host_ip);
int read_size = 0;
char readBuf[256];
if((read_size = recv(client_sock , readBuf , 256 , 0)) > 0){
printf("readBuf: %s\r\n",readBuf);
strcpy(arr[k+1],readBuf);
memset(readBuf,0,256);
}
else{
printf("Receive has failed.. read_size: %d\r\n",read_size);
}
}
else {
int read_size;
char readBuf[256];
if((read_size = recv(client_sock , readBuf , 256 , 0)) > 0){
printf("readBuf: %s\r\n",readBuf);
strcpy(arr[k+2],readBuf);
memset(readBuf,0,256);
}
else{
printf("Receive has failed.. read_size: %d\r\n",read_size);
}
}
}
close(client_sock);
close(socket_desc);
return arr;
}
Client part —— connect() and fwrite() successful
void give_envi(char* env_var) {
printf("The environment variable sent: %s\r\n",env_var);
int receive_no = 1;
int sock;
struct sockaddr_in server;
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
//puts("Socket created");
//char host_ip[20];
//strcpy(host_ip,getenv("HOST_IP"));
server.sin_addr.s_addr = inet_addr("127.0.0.1"); //PROVIDE THE IP OF THE TARGET TO SEND YOUR DATA.
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );
int reuse = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEADDR) failed");
}
if(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEPORT) failed");
}
//Connect to remote server
if ( connect(sock , (struct sockaddr *)&server , sizeof(server)) > -1) {
puts("Connection established!\r\n");
}
else{
puts("Connection failed\r\n");
}
FILE * file = fdopen(sock, "w");
if(fwrite (env_var ,sizeof(char), strlen(env_var), file) == strlen(env_var)){
printf("fwrite() SUCCESS\r\n");
}
else{
printf("FAILED on fwrite()\r\n");
}
close(sock);
}

Related

Orchestration for a simple server in C

I'm trying to make a simple multi-thread server in C, and I would like to make a queue for clients, so no one drops connection.
But I have no idea what to do and where to start.
Anyone can help? Any advices would be appreciated :)
and I had to remove the thread function code because code was too long that this question won't post.
int main(int argc, char const *argv[])
{
int server_fd, new_socket; //long valread;
struct sockaddr_in address;
int addrlen = sizeof(address);
pthread_t tid[1024];
int i = 0; // index for tid array
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("In socket");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
memset(address.sin_zero, '\0', sizeof address.sin_zero);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("In bind");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 10) < 0)
{
perror("In listen");
exit(EXIT_FAILURE);
}
while(1)
{
printf("\n+++++++ Waiting for new connection ++++++++\n\n");
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("In accept");
exit(EXIT_FAILURE);
}
if( pthread_create(&tid[i++], NULL, thread, &new_socket) != 0 )
printf("Failed to create thread\n");
if( i >= 1024 )
i = 0;
}
return 0;
}

How to send a message from server to client in C

Hey guys I want to send a message of the current date from the server to a client in C.
So I would use a command like this for the client;
Terminal
telnet localhost PORT
What should be the command to send the actual message?
int main(int argc, char *argv[])
{
int socket_desc, client_sock, c, read_size;
struct sockaddr_in server, client;
char client_message[2000];
time_t t = time(NULL);
struct tm tm = *localtime(&t);
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
listen(socket_desc, 3);
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
puts("Connection accepted");
////////////////////////////////////////////////////
//the actual message here
////////////////////////////////////////////////////
close(socket_desc);
return 0;
}
I made the following addiction and it worked
Is this a proper solution? I don't know how to use send() properly yet.
pid_t child_pid = fork();
if (child_pid == 0)
{
snprintf(client_message, sizeof(client_message), "%s", ctime(&tick));
write(client_sock, client_message, strlen(client_message));
shutdown(client_sock, SHUT_RDWR);
while (read(client_sock, client_message, sizeof(client_message) > 0))
close(client_sock);
}
else if (child_pid > 0)
{
// parent
close(client_sock);
}
else
{
// a fork error occurred, handle and remember to close(connfd)
}

Connection Refused even after adding a new Firewall rule

I am trying to connect to my local UNIX server i made from another remote device. the Server is up and listening to the port i specified. i also added a new firewall rule to open that port but still my client cannot connect. it shows ERROR CONNECTION REFUSED
here is my server code
int main() {
int fd, i,svclient,rval,msg;
int clients[10], num_clients;
fd_set read_set,write_set;
char buf[100];
struct sockaddr_in addr;
if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(4001);
//strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
//strcpy(addr.sun_path, NAME);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
exit(-1);
}
printf("Bind complet...\n");
if (listen(fd, 20) == -1) {
perror("listen error");
exit(-1);
}
num_clients = 0;
int size = sizeof(fd);
while (1) {
int clientfd;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
for (i = 0; i < num_clients; i++) { //at first this part will not excute
FD_SET(clients[i], &read_set);
}
select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(fd, &read_set)) {
if ( (clients[num_clients++] = accept(fd,(struct sockaddr*)&client_addr,&addrlen)) == -1) {
perror("accept error");
continue;
}
/*printf("incoming message..................... !\n \n");*/
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
for (i = 0; i < num_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
msg = read(clients[i], buf, sizeof(buf));
if(msg > 0){
buf[msg] = 0;
int savedclnt = clients[i];
printf("%s \n \n", buf);
/*for(int p=0;p<num_clients;p++)
{
if( clients[p]!= savedclnt){
write(clients[p],buf,msg);
}
}*/
}
}
}
}
}
and my client
int main( )
{
struct uci_context *uci;
uci = uci_init();
int sockfd;
int ret;
struct sockaddr_in dest;
struct addrinfo hint, *res = NULL;
struct hostent *host;
char *hostip;
char *string;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
puts("Unble to create socket");
exit(1);
}
hostip = ucix_get_option(uci, "pack_mon", "pack_monitoring", "address");
string = ucix_get_option(uci, "pack_mon", "pack_monitoring", "port");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(string));
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
printf(" %s- %s\n", hostip, string );
if(isdigit(hostip[0])){
ret = getaddrinfo(hostip, NULL, &hint, &res);// this is more efficient than inet_addr
if (ret) {
exit(1);
}
}else if( (host = gethostbyname(hostip)) != 0){
memcpy((char*)&dest.sin_addr , (char*)host->h_addr , (sizeof dest.sin_addr)+1);
}else{
exit(1);
printf("cannot resolve ip address");
}
if ( connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0 )
{
perror("ERROR Connecting" );
exit(1);
}else{
printf("Port number %s is open.....\n",string);
}
char *message;
message = "help";
write(sockfd,message,strlen(message));
close(sockfd);
freeaddrinfo(res);
return 0;
}
FIREWALL RULE
sudo iptables -I INPUT -p tcp --dport 4001 -j ACCEPT
Error is :
192.168.10.155- 4001
ERROR Connecting: Connection refused
and this logs are coming from this codes :
printf(" %s- %s\n", hostip, string );
perror("ERROR Connecting");
exit(1);
Your client has no code to specify the IP address it wants to connect to. All the code that could do that has been commented out.
Update: Now your bug is here:
strncpy((char*)&dest.sin_addr , (char*)host->h_addr , sizeof dest.sin_addr);
The strncpy function is only suitable for C-style strings. You need to use memcpy or something similar. This will only copy part of the IP address if any octet other than its last one (in network byte order) is zero.
Update: Now your bug is here:
printf("%d\n", connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0);
perror("hmmmm" );
exit(1);
This calls connect, then calls printf and then calls perror. The problem is, the call to printf can modify errno even if it succeeds. Thus your call to perror can print a totally irrelevant error message.

Error connection to remote server in socket programming using c

It is a sample code where i have tried to pass a request to server and get me the desired data.
But my connect to remote server code is not working as i thought.
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
I don't know why value of the condition is getting below zero.Why connection is not getting done?
Full code:
/*
Create a TCP socket
*/
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char *message , server_reply[2000];
int recv_size;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
server.sin_addr.s_addr = inet_addr("74.125.235.20");
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
//Connect to remote server
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
//Send some data
message = "GET / HTTP/1.1\r\n\r\n";
if( send(s , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");
//Receive a reply from the server
if((recv_size = recv(s , server_reply , 2000 , 0)) == SOCKET_ERROR)
{
puts("recv failed");
}
puts("Reply received\n");
//Add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
closesocket(s);
WSACleanup();
return 0;
}
You need to initalize the whole sockaddr_in to zero before assigning to it.
memset( &server, 0, sizeof(server) );
server.sin_addr.s_addr = inet_addr("74.125.235.20");
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
I copied your code and tried it out and it seemed to work, maybe you have a firewall that is interfering.
BTW I changed your inet_addr call to
InetPtonA( AF_INET, "74.125.235.20", &server.sin_addr.s_addr );

TCP Sockets, "cannot assign requested address" and " Transport endpoint is already connected" errors

I am new to working with TCP sockets and I do not understand the errors I am getting when running my programs. I have two programs that when run simultaneous I would like to be able to pass messages between. The initial message gets through but then when trying to return another message I get two errors. When I run my first program the output is:
Input Message: hello
Waiting for incoming connections...
Connection accepted
Message Sent
Connection error: Transport endpoint is already connected
Now running the other program simultaneously gives:
Input Message: Hello Back
Connected
Message received
hello
Bind error: Cannot assign requested address
If anyone could explain these "cannot assign requested address" and " Transport endpoint is already connected" errors I would greatly appreciate it!! Thanks!
The first program is:
int main(int argc, char *argv[]) {
int socket_info, new_socket;
struct sockaddr_in server, client;
char message[100];
char incoming_message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
//create socket
socket_info = socket(AF_INET, SOCK_STREAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign values
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
int y=1;
if(setsockopt(socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
return -1;
}
//binds socket
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Bind error");
return 1;
}
//listen
listen(socket_info , 5);
//waiting for connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
//accept connection
new_socket = accept(socket_info, (struct sockaddr *)&client, (socklen_t*)&c);
if (new_socket < 0){
perror("accept failed");
return 1;
}
puts("Connection accepted");
//send message
if( send(new_socket , message , strlen(message) , 0) < 0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
//connects
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//Receive an incoming message
if( recv(socket_info, incoming_message , sizeof(incoming_message) , 0) < 0) {
perror("Received failed");
return 1;
}
puts("Message received");
incoming_message[strlen(incoming_message)-1]=0;
puts(incoming_message);
close(socket_info);
}
The second program is:
int main(int argc, char *argv[]) {
int socket_info, new_socket;
struct sockaddr_in server, client;
char incoming_message[100];
char message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
//create socket
socket_info = socket(AF_INET, SOCK_STREAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign values
server.sin_addr.s_addr = inet_addr("172.21.8.178");
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
//connects
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//Receive an incoming message
if( recv(socket_info, incoming_message , sizeof(incoming_message) , 0) < 0) {
perror("Received failed");
return 1;
}
puts("Message received");
incoming_message[strlen(incoming_message)-1]=0;
puts(incoming_message);
int y=1;
if(setsockopt(socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
return -1;
}
//binds socket
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Bind error");
return 1;
}
//listen
listen(socket_info , 5);
//waiting for connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
//accept connection
new_socket = accept(socket_info, (struct sockaddr *)&client, (socklen_t*)&c);
if (new_socket < 0){
perror("accept failed");
return 1;
}
puts("Connection accepted");
//send message
if( send(new_socket , message , strlen(message) , 0) < 0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
close(socket_info);
}
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
Connection error: Transport endpoint is already connected
I asssume socket_info above should be new_socket?
You can't connect a listening socket.
You don't need to connect the listening socket. You have just accepted a socket from a client connection. You should do your I/O to that client with that socket.
In your second program:
if(setsockopt(socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
return -1;
}
This is futile. The socket is already bound, implicitly, via the connect() call preceding.
//binds socket
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Bind error");
return 1;
}
Bind error: Cannot assign requested address
You can't bind a socket that is already connected.
Nor can you bind a socket to a remote address.
Nor can you listen on a connected socket.
Nor can you accept from it. You don't need to bind, or listen, or accept from it. You are already connected to the peer.
In short your code doesn't make any sense whatsoever. You need to find a proper tutorial and study it.
incoming_message[strlen(incoming_message)-1] = 0;
This makes even less sense. Here you are searching for a trailing null byte (which may not even be there) and replacing the byte before it by ... a null byte. Why?

Resources