Sockets_Client_Server_communication_Linux_C - c

Hi Today I was trying to learn socket communication in c and Linux ,But my below code not working as expected. I am not able to find the problem though I understand where the error is occuring.
server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
char data[100];
int main()
{
int socket_descrp,server_len;
socket_descrp = socket(AF_UNIX,SOCK_STREAM,0);
if(socket_descrp<0)
{
perror("server Socket failed\n");
exit(1);
}
struct sockaddr_un server,client;
int clientlen;
server.sun_family = AF_UNIX;
strcpy(server.sun_path,"mysocket");
unlink("mysocket");
server_len = sizeof(server);
if(bind(socket_descrp,(struct sockaddr *)&server,server_len)<0){
printf("bind error\n");
exit(1);
}
if(listen(socket_descrp,1)<0)
{
printf("listen error\n");
exit(1);
}
if(accept(socket_descrp,(struct sockaddr*)&client,&clientlen)<0)
{
printf("accept error\n");
exit(1);
}
if(read(socket_descrp,data,99)<0)
{
perror("Error occured in reading\n");
exit(1);
}
else if(read(socket_descrp,data,99)==0)
{
printf("No bytes are read\n");
exit(1);
}
else
printf("Reading from client\n");
printf("The read content is: %s\n",data);
close(socket_descrp);
return 0;
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
char data[100]="Hello World!";
int main()
{
int socket_descrp,client_len;
socket_descrp = socket(AF_UNIX,SOCK_STREAM,0);
if(socket_descrp<0)
{
perror("client Socket failed\n");
exit(1);
}
struct sockaddr_un client;
client.sun_family = AF_UNIX;
strcpy(client.sun_path,"mysocket");
client_len = sizeof(client);
if(connect(socket_descrp,(struct sockaddr*)&client,client_len)<0)
{
printf("Connection error\n");
exit(1);
}
if(write(socket_descrp,data,strlen(data))<0)
{
printf("Error writing to the socket\n");
exit(1);
}
return 0;
}
The error message printed is "Error occured in reading: invalid argument" on the server executable file. I am not able to understand why can't it read.
Client executable is not printing any error message. I spent nearly 2 hours trying to find the problem. :(

You cannot read from the server socket. accept returns a socket to communicate through:
client_sock = accept(socket_descrp, ...);
read(client_sock, ...);

Related

Cannot print code received by client using sockets in C

I don know why i can't print the information saved into my client's buffer. Firstly, the code i'm transfering from server to client is the source code of google main page. I've saved this code in a html file and the size of the whole file is 198357 bytes.
For this, i used a buffer of 1024 bytes and i've passed all the data inside loops.
I've been checking using prints the number of bytes passed by the server and received by client and both are equal to the number of bytes of the file, so the transferation is well done.
But when i try to print this data saved into the buffer it starts giving me problems.
server.c
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr=INADDR_ANY;
serverAddress.sin_port = htons(9999);
int server = socket(AF_INET,SOCK_STREAM,0);
if(server == -1)
{
perror("Cannot open the socket");
exit(1);
}
int active = 1;
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &active, sizeof(active));
if(bind(server, (void*)&serverAddress, sizeof(serverAddress)) !=0)
{
perror("Fail bind");
exit(1);
}
else
{
printf("success\n");
}
printf("I'm listening\n");
listen(server, SOMAXCONN);
//----------------------------------------------------
while(1)
{
struct sockaddr_in clientAddress;
unsigned int addressSize;
int client = accept(server, (struct sockaddr*)&clientAddress, &addressSize);
int child = fork();
if(child==0) //in case we stablished a connection we have to create a child and then transfer the file inside of it
{
int file = open("google.html",O_RDONLY); //open file
if(file <0)
{
perror("Empty file!\n");
return 1;
}
while(1) //Iterate until function read cannot read more bytes
{
unsigned char buffer[1024]={0};
int read_bytes = read(file,buffer,sizeof(buffer));
if(read_bytes==0)
{
printf("Transfer!\n");
break;
}
while(read_bytes>0) //Write on the client the reading bytes
{
int written_bytes;
written_bytes = write(client, buffer, read_bytes);
//printf("%d\n",written_bytes); //print to check how many bytes are passed to the client (1024)
read_bytes -= written_bytes; //breaks loop
}
}
}
close(server);
shutdown(server, SHUT_RDWR);
sleep(1);
break;
}
return 0;
}
client.c
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv)
{
if(argc ==2) //you've got to received as an argument the IP of the server, i haven't implemented it yet!
{
int client = socket(AF_INET,SOCK_STREAM,0);
char recvBuffer[1024];
int n=0, s;
if(client <0)
{
printf("Cannot open the socket\n");
exit(1);
}
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr=INADDR_ANY;
serverAddress.sin_port = htons(9999);
if(connect(client, (void*)&serverAddress, sizeof(serverAddress)) !=0)
{
perror("Cannot be connected");
return 1;
}
printf("Connecting!");
char buffer2[1024];
while((n=read(client, recvBuffer,sizeof(recvBuffer)-1))>0)
{
//printf("%d\n",n); //i used to check the num of bytes passed by this and everything it's correct
recvBuffer[n] =0;
printf("%s",recvBuffer); //error, the transferation goes wrong here
}
if(n==0)
{
shutdown(client, SHUT_RD);
close(client);
}
else if(n<0)
{
perror("Read error\n");
return 1;
}
}
return 0;
}

Reusing linux abstract namespace socket

I would like to reuse one abstract socket adress during one server session. I tried to close sockets and bind them again, but it isn't working.
server.c:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int main()
{
struct sockaddr_un workmanaddr;
workmanaddr.sun_family=AF_UNIX;
strcpy(workmanaddr.sun_path+1,"name");
workmanaddr.sun_path[0]='0';
char buf[255];
int sd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(sd <0)
{
perror("socket() error");
exit(2);
}
if((bind(sd , (struct sockaddr *)&workmanaddr,sizeof(workmanaddr)))<0)
{
perror("bind() error");
exit(3);
}
while(true)
{
recv(sd, buf, sizeof(buf), 0);
printf("%s\n",buf);
close(sd);
sd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(sd <0)
{
perror("socket() error");
exit(2);
}
if((bind(sd , (struct sockaddr*)&workmanaddr,sizeof(workmanaddr)))<0)
{
perror("bind() error");
exit(3);
}
}
return 0;
}
client.c:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int main(int argc, char *argv[])
{
char _path[108]="name";
struct sockaddr_un tempadres = {0};
int tmpsock;
tmpsock = socket(AF_UNIX, SOCK_DGRAM, 0);
if(tmpsock<0)
{
perror("socket() error");
exit(2);
}
tempadres.sun_family=AF_UNIX;
strcpy(tempadres.sun_path+1,_path);
tempadres.sun_path[0]='0';
if((connect(tmpsock, (struct sockaddr *)&tempadres,sizeof(tempadres)))<0)
{
perror("connect() error");
exit(3);
}
char buf[255];
scanf("%s",buf);
if(send(tmpsock, buf, sizeof(buf), 0)<0)
{
perror("send() error");
exit(4);
}
return 0;
}
What should I do to make it possible to reuse it many times? Any advices?
In this line: tempadres.sun_path[0]='0','0' is not null byte what abstract socket requires for the first byte of the sun_path field. So it wouldn't be regarded as abstract socket. Change it to tempadres.sun_path[0]=0 or tempadres.sun_path[0]='\0'.
PS: there is another problem in your server.c, you didn't zero out workmanaddr, so the sun_path is very likely to contain garbage value as it's allocated on the stack even though you called strcpy(workmanaddr.sun_path+1,"name"); and a null byte is appended because all the remaining bytes in sun_path define the "name" of the socket. it would lead to different socket names with the client, resulting in connection refused on client side.

c socket file transfer, server does not open existing file

I am writing simple client-server program. Essentially I am following example from "Linux Network Programming" book. This is simple TCP server
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#define SERVERPORT 8888
#define MAXBUF 1024
int main(int argc, char* argv[])
{
int socket1, socket2;
int addrlen;
struct sockaddr_in fServer, fClient;
int status;
socket1=socket(AF_INET, SOCK_STREAM, 0);
if(socket1==-1)
{
printf("Could not create the socket\n");
exit(1);
}
fServer.sin_family=AF_INET;
fServer.sin_addr.s_addr=INADDR_ANY;
fServer.sin_port= htons(SERVERPORT);
status=bind(socket1, (struct sockaddr*) &fServer,
sizeof(fServer));
if(status==-1)
{
printf("could not bind the socket\n");
exit(1);
}
else printf("socket is created\n");
status=listen(socket1, 5);
if(status==-1)
{
printf("could not listen socket\n");
exit(1);
}
else printf("socket is waiting for connection\n");
for(;;)
{
int fd;
int i, readCounter, writeCounter;
char* bufptr;
char buf[MAXBUF];
char filename[MAXBUF];
addrlen=sizeof(fClient);
socket2=accept(socket1, (struct sockaddr*) &fClient, &addrlen);
if(socket2==-1)
{
printf("could not accept connection\n");
exit(1);
}
else printf("connection established, waiting for the file name\n");
i=0;
if((readCounter=read(socket2, filename, MAXBUF))>0)
i+=readCounter;
filename[i+1]='\0';
printf("reading from the file\n");
fd=open(filename, O_RDONLY);
if(fd==-1)
{
printf("could not open the file\n");
perror(" error is detected: ");
close(socket2);
continue;
}
else printf("file name is recieved, started copying\n");
readCounter=0;
while((readCounter=read(fd, buf, MAXBUF))>0)
{
writeCounter=0;
bufptr=buf;
while(writeCounter<readCounter)
{
readCounter-=writeCounter;
bufptr+=writeCounter;
writeCounter=write(socket2, bufptr, readCounter);
if(writeCounter==-1)
{
printf("could not write the file to client\n");
close(socket2);
continue;
}
}
}
close(fd);
close(socket2);
}
close(socket1);
return 0;
}
This code is for client.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#define SERVERPORT 8888
#define MAXBUF 1024
int main(int argc, char* argv[])
{
int sockd;
int counter;
int fd;
struct sockaddr_in fServer;
char buf[MAXBUF];
int status;
if(argc<3)
{
printf("Incorrect data provided\n");
exit(1);
}
sockd=socket(AF_INET, SOCK_STREAM,0);
if(sockd==-1)
{
printf("could not create socket\n");
exit(1);
}
fServer.sin_family=AF_INET;
fServer.sin_addr.s_addr=inet_addr(argv[1]);
fServer.sin_port=htons(SERVERPORT);
status=connect(sockd, (struct sockaddr*)&fServer,
sizeof(fServer));
if(status==-1)
{
printf("could not connect to server\n");
exit(1);
}
status=write(sockd, argv[2], strlen(argv[2]+1));
if(status==-1)
{
printf("could not send file name to server\n");
exit(1);
}
shutdown(sockd, SHUT_WR);
fd=open(argv[2], O_WRONLY| O_CREAT| O_APPEND);
if(fd==-1)
{
printf("could not open destination file\n");
exit(1);
}
while((counter=read(sockd, buf, MAXBUF))>0)
{
write(fd, buf, counter);
}
if(counter==-1)
{
printf("file transfer is complete\n");
exit(1);
}
printf("file transfer is complete\n");
close(sockd);
return 0;
}
I pass file name from the same directory as server. I pass filename as agrc[2] parameter. Server oputput however is the following
socket is created
socket is waiting for connection
connection established, waiting for the file name
reading from the file
could not open the file
error is detected: : No such file or directory
connection established, waiting for the file name
reading from the file
could not open the file
error is detected: : No such file or directory
I entered the filename on my first attempt, then I enterd full path but still recieving the same message. So what is the problem? thanks in advance
Client:
status=write(sockd, argv[2], strlen(argv[2]+1));
strlen(argv[2]+1) should be strlen(argv[2])+1 if you want to include the \0.also: you do not close your fd. close(sockd); should be close(fd);
Server:
filename[i+1]='\0'; should be filename[i]='\0'; if you are not sure you received the \0.
if you are sending 1 char, for example 'a', i would be 1 and your array would look like
filename[0] = 'a'
filename[i] = undefined
filename[i+1] = '\0'
Unrelated to your problem, but on the server side you should advance bufptr after write(), not before.
Also: TCP is a stream protocol; there is no guarantee that a write() on one end of a connection will be completely read by a single recv() on the other end.

Connection refused TCP sockets

I made a simple client and a simple server with TCP sockets.When I was testing them, I got an error message: Connection refused.
I have opened the ports for the server, so I don't understand why I get this error... Can you help me?
This is the client's source
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#define PORTA 3459
int main()
{
char indirizzo[15];
char buffer[20];
struct sockaddr_in client;
int clients;
puts("Inserire l'indirizzo");
fgets(indirizzo, 15, stdin);
printf("L'indirizzo del destinatario è %s",indirizzo);
puts("Inserire il messaggio");
fgets(buffer, 20, stdin);
client.sin_family = AF_INET;
client.sin_port = htons(PORTA);
client.sin_addr.s_addr = inet_addr(indirizzo);
memset(client.sin_zero, '\0',8);
if((clients = socket(PF_INET, SOCK_STREAM,0)) == -1)
{
printf("%s\n", strerror(errno));
exit(0);
}
if( (connect(clients, (struct sockaddr *)&client, sizeof(structsockaddr)) ) == -1)
{
printf("%s\n", strerror(errno));
exit(0);
}
send(clients, buffer, 20,0);
close(clients);
return 0;
}
This is the server's source code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#define PORTA 3459
int main()
{
struct sockaddr_in sock;
int socks;
struct sockaddr_in newsock;
int newsocks;
if((socks = socket(PF_INET, SOCK_STREAM,0)) == -1)
{
puts("Errore: socks non inizializzato\n");
printf("%s\n", strerror(errno));
exit(0);
}
sock.sin_family = AF_INET;
sock.sin_port = htons(PORTA);
sock.sin_addr.s_addr = htonl(INADDR_ANY);
memset(sock.sin_zero, '\0',8);
int si = 1;
if(setsockopt(socks,SOL_SOCKET,SO_REUSEADDR,&si,sizeof(int)) == -1)
{
puts("Errore durante il settaggio del socket\n");
printf("%s\n", strerror(errno));
exit(0);
}
if(bind(socks,(struct sockaddr *)&sock, sizeof(struct sockaddr) ) == -1)
{
puts("Errore durante il binding\n");
printf("%s\n", strerror(errno));
exit(0);
}
char buffer[30];
int lung;
lung = sizeof(newsock);
listen(socks, 5);
if((newsocks = accept(socks,(struct sockaddr *)&newsock,&lung)) == -1)
{
puts("Errore durante l'accettazione del socket remoto\n");
printf("%s\n", strerror(errno));
exit(0);
}
if(recv(newsocks, buffer,sizeof(buffer),0) == -1)
{
puts("Errore durante la ricezione dei dati");
printf("%s\n", strerror(errno));
}
puts(buffer);
return 0;
}
Code looks good in general, except for not controlling errors in some cases (inet_addr) and the ports are the same both in client and server. If you get connetion refused error, it cannot be a firewall-related problem.
Do you have the same error always or sometimes it works OK?
Most probably the problem is one of these:
1-Client is trying to connect to the wrong IP address. Check the address printed and result of inet_addr.
2-The server doesn't have a loop to keep listening for connections. It finishes after getting one connection. Maybe a first test works then server ends and client is run again getting connection refused.
You could also try not setting SO_REUSEADDR. I don't think it's related but if nothing else works ...

Why does this server not outputting anything?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
int main()
{
int sock, newsock;
struct sockaddr server_name = {AF_UNIX, "Fred"};
socklen_t len=sizeof(struct sockaddr)+5;
if( (sock=socket(AF_UNIX,SOCK_STREAM,0)) ==-1)
{
printf("error creating socket");
return -1;
}
if( bind(sock,&server_name,len) != 0 ) //binding
{
printf("socket bind error ");
return -1;
}
if(listen(sock,10)!=0) //set sock to listen
{
printf("error listening");
return -1;
}
printf("Waiting for connections....");
while(1)
{
newsock=accept(sock, (struct sockaddr*)NULL, NULL);
char temp[1000]="gggggg\n";
write(newsock,temp,strlen(temp));
write(newsock,temp,strlen(temp));
close(newsock);
sleep(1);
}
return 0;
}
"Waiting for connections..." doesn't appear on my screen. What's the problem? I tried print function everywhere. Nothing shows up..What is the problem? I don't see that I closed stdout..Can anyone help? Thank you.
The standard output is line buffered by default. Your program outputs something without the new line and then enters the loop. You need to add a new line like this:
printf("Waiting for connections....\n");
For similar reasons, the error messages should be output to standard error, because it's not buffered.
fprintf(stderr, "error creating socket\n");
Firstly, you should add '\n' add the end of log:"Waiting for connections....\n", then the log cann't be buffered, and be outputted.
Secondly, your program is error, the correct program is like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int main()
{
int sock, newsock;
struct sockaddr_un server_name;
socklen_t len= sizeof(server_name);
unlink("Fred");
if( (sock=socket(AF_UNIX,SOCK_STREAM,0)) ==-1)
{
printf("error creating socket\n");
return -1;
}
server_name.sun_family = AF_UNIX;
strcpy(server_name.sun_path, "Fred");
if( bind(sock,(struct sockaddr*)&server_name,len) != 0 ) //binding
{
printf("socket bind error \n");
return -1;
}
if(listen(sock,10)!=0) //set sock to listen
{
printf("error listening\n");
return -1;
}
printf("Waiting for connections....\n");
while(1)
{
newsock=accept(sock, (struct sockaddr*)NULL, NULL);
char temp[1000]="gggggg\n";
write(newsock,temp,strlen(temp));
write(newsock,temp,strlen(temp));
close(newsock);
sleep(1);
}
return 0;
}

Resources