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.
Related
My server and client are communicating back and forth using two named pipes (fifo) in C until the server receives an exit message.
Apparently the server side blocks the second time it tries to read() from its FIFO despite the client writing to it successfully. I think the problem is that the server tries to read() sooner than the client could write() to it.
Here is the server:
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "header.h"
#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
//fifo for the server to read from
if (mkfifo(FIFONAME, S_IFIFO|0666) < 0) {
if (errno != EEXIST) {
perror("Error with mkfifo");
exit(1);
}
}
int f;
if ((f = open(FIFONAME, O_RDONLY)) < 0) {
perror("Error with open");
exit(1);
}
Message msg;
while(1) {
if ((read(f, &msg, sizeof(Message))) > 0) {
if (strcmp(msg.user, "exit") == 0) {
close(f);
unlink(FIFONAME);
exit(0);
}
if (strcmp(msg.user, "new client") == 0) {
switch (fork()) {
case -1:{
perror("Error with fork");
exit(1);
}
case 0:{
char gender[MAXLEN];
char client_fifo[30];
sprintf(msg.user, "I need client's gender\n");
sprintf(client_fifo, "fifo_%d", msg.pid);
msg.pid = getpid();
int o;
//open client's fifo for server to write to
if ((o = open(client_fifo, O_WRONLY)) == -1) {
perror("Error opening client fifo");
exit(1);
}
//send message
write(o, &msg, sizeof(Message));
//read client's answer, but program blocks here
if ((read(f, &msg, sizeof(Message))) > 0) {
sprintf(gender,"%s", msg.user);
printf("Client's gender is %s\n", gender);
}
close(o);
exit(0);
}
}
}
}
}
return 0;
}
The client code:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "header.h"
#include <unistd.h>
int f,fc;
char fifoname[20];
Message msg;
int main(int argc, char* argv[]) {
sprintf(fifoname, "fifo_%d", getpid());
if (mkfifo(fifoname, S_IFIFO | 0666) < 0) {
perror("Error with client's fifo");
printf("Could not create fifo_%d", getpid());
exit(1);
}
if ((f=open(FIFONAME,O_WRONLY))<0) {
perror("Error connecting to server");
exit(2);
}
char gender[MAXLEN];
strcpy(msg.user, "new client");
msg.pid = getpid();
//first message to server
write(f, &msg, sizeof(msg));
char arg[MAXLEN];
if (argc > 1) {
strcpy(arg, argv[1]);
} else {
strcpy(arg, "work");
}
if (strcmp(arg, "exit")) {
if ((fc = open(fifoname, O_RDONLY))<0) {
perror("Error opening client's fifo");
printf("Could not open my fifo");
exit(3);
}
if (read(fc, &msg, sizeof(msg)) > 0) {
printf("%s\n",msg.user);
}
scanf("%s", gender);
strcpy(msg.user, gender);
msg.pid = getpid();
printf("writing gender...\n");
write(f, &msg, sizeof(msg));
//program successfully reaches this print:
printf("gender written\n");
close(fc);
}
unlink(fifoname);
close(f);
exit(0);
}
And the header containing the struct for the message:
#define MAXLEN 20
typedef struct {
int pid;
char user[MAXLEN];
} Message;
#define FIFONAME "fifo_server"
I need to write further back and forth messages like this but I don't know how to get the server not to block on the second call of read()
I'm trying to write a C program for a client which can download a file from the server using TCP. The client will print and save the file content after it receives the file from the server. To compile the client program it needs IP address and port number of the server. I implemented it in Linux but it displayed 0s after the received texts. The saved text file was the same. I have no idea how to output the text only. Maybe there are wrongs in the receive buffer?
Code for server:
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
#define portnum 12345
#define FILE_SIZE 500
#define BUFFER_SIZE 1024
void *client_fun(void * fd);
int main()
{
int new_fd;
pthread_t thread_id;
int server_fd=socket(AF_INET,SOCK_STREAM,0);
if(-1==server_fd)
{
perror("socket");
exit(1);
}
struct sockaddr_in server_addr;
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnum);
(server_addr.sin_addr).s_addr=htonl(INADDR_ANY);
if(-1==bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)))
{
perror("bind");
close(server_fd);
exit(6);
}
if(-1==listen(server_fd,5))
{
perror("listen");
close(server_fd);
exit(7);
}
while(1)
{
struct sockaddr_in client_addr;
int size=sizeof(client_addr);
new_fd=accept(server_fd,(struct sockaddr *)&client_addr,&size);
if(new_fd < 0)
{
perror("accept");
continue;
}
printf("accept client ipé”›?s:%d\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
//printf("new_fd=%d\n",new_fd);
if (new_fd > 0)
{
pthread_create(&thread_id, NULL, client_fun, (void *)&new_fd);
pthread_detach(thread_id);
}
}
close(server_fd);
return 0;
}
void *client_fun(void *arg)
{
int new_fd = *((int *)arg);
int file2_fp;
int len;
char buffer[BUFFER_SIZE];
memset( buffer,0, sizeof(buffer) );
while(1)
{
if((len=recv(new_fd, buffer, sizeof(buffer), 0)) <= 0)
{
continue;
}
char file_name[FILE_SIZE];
memset( file_name,0, sizeof(file_name) );
strncpy(file_name, buffer, strlen(buffer)>FILE_SIZE?FILE_SIZE:strlen(buffer));
memset( buffer,0, sizeof(buffer) );
printf("Client requests file %s\n", file_name);
if( strcmp(file_name,"exit")==0 )
{
break;
}
file2_fp = open(file_name,O_RDONLY,0777);
if(file2_fp<0)
{
printf("File %s Not Found\n", file_name);
char* err_info = "File not found\n";
if (write(new_fd, err_info, sizeof(err_info)) < 0)
{
printf("Send error information failed\n");
break;
}
continue;
}
else
{
int length = 0;
memset( buffer,0, sizeof(buffer) );
while( (length = read(file2_fp, buffer, sizeof(buffer))) > 0 )
{
if( write(new_fd, buffer, length) < 0)
{
printf("Send File %s Failed.\n", file_name);
break;
}
memset( buffer,0, sizeof(buffer) );
}
close(file2_fp);
printf("Transfer file %s successfully!\n", file_name);
}
}
close(new_fd);
}
Code for client:
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
int main(int argc, char *argv[])
{
int sockfd = 0;
char recvBuff[1024];
char file_name[500];
char *serverIP=argv[1];
int portno=atoi(argv[2]);
printf("IP Addresses: %s Port Number: %s\n", argv[1], argv[2]);
memset(recvBuff,'0',sizeof(recvBuff));
struct sockaddr_in server_addr;
/* Creat a socket*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/*Initialize sockaddr_in structure*/
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portno);
(server_addr.sin_addr).s_addr=inet_addr(serverIP);
/*Attempt a connection*/
printf("Connect status: ");
if (connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr))<0)
{
printf("fail\n");
return 0;
}
printf("success\n");
/*Request file from server*/
while(1)
{
printf("Input the file name to be requested from the server: ");
fgets(file_name,500, stdin);
char *p=strchr(file_name,'\n');
if (p) *p=0;
if (send(sockfd, file_name, strlen(file_name), 0)<0)
{
printf("Send failed.\n");
break;
}
printf("Send success.\n");
if (strcmp(file_name,"exit")==0)
break;
int length=0;
printf("Send status: ");
if (length=read(sockfd, recvBuff, sizeof(recvBuff))<0)
{
printf("fail\n");
continue;
}
else if (strcmp(recvBuff,"File not found\n")==0)
{
printf("fail\n");
continue;
}
else
{
printf("success\n");
/*Create file where text will be stored*/
FILE *fp;
fp=fopen("received_file.txt","w");
printf("Open file status: ");
if (fp==NULL)
{
printf("fail\n");
continue;
}
printf("success\n");
printf("Received text: ");
if (fprintf(fp, "%s", recvBuff)<0)
{
printf("Save status: fail\n");
continue;
}
fflush(fp);
printf("%s",recvBuff);
memset(recvBuff,0,1024);
while ((length=read(sockfd, recvBuff, sizeof(recvBuff)))>0)
{
if (fprintf(fp, "%s", recvBuff)<0)
{
printf("Save status: fail\n");
break;
}
fflush(fp);
printf("%s",recvBuff);
memset(recvBuff,0,1024);
}
printf("Save status: success");
}
}
}
Another question is that the client is supposed to keep asking for files until it sends an 'exit'. But it stopped asking the client to input the file name after the first file was received. What's wrong with the loop?
you have several issues.
first: - comparison operator has precedence over assignment so length gets FALSE(0) value instead of the real number of received data
if (length=read(sockfd, recvBuff, sizeof(recvBuff))<0)
it should be:
if ((length=read(sockfd, recvBuff, sizeof(recvBuff)))<0)
second: you are operating with zero terminated strings but you do not send zero ('\0') from server and client does not set it at the end of the data block.
So you need to set it explicitly at client side here
if ((length=read(sockfd, recvBuff, sizeof(recvBuff)))<0)
{
printf("fail\n");
continue;
}
else if (strcmp(recvBuff,"File not found\n")==0)
{
printf("fail\n");
continue;
}
else
{
recvBuff[length]='\0';
and here:
while ((length=read(sockfd, recvBuff, sizeof(recvBuff)))>0){
recvBuff[length]='\0';
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/socket.h> //Unable to find all of this header files
#include <signal.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <netdb.h>
I want to use this header files ion my program and i cannot find it on the internet please provide a source from which i could get them
On windows, socket api is packed into a different set of headers. But the way the windows sockets work (if used in a "portable" way) is pretty much the same as on unix systems. Give or take.
The example code from the other question you linked looks like this on windows:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
//#include <netinet/in.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
//#include <sys/wait.h>
//#include <sys/socket.h>
//#include <signal.h>
#include <ctype.h>
//#include <arpa/inet.h>
//#include <netdb.h>
#define PORT 20000
#define LENGTH 512
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
/* Variable Definition */
SOCKET sockfd;
char revbuf[LENGTH];
struct sockaddr_in remote_addr;
/* Get the Socket file descriptor */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "ERROR: Failed to obtain Socket Descriptor! (errno = %d)\n", errno);
exit(1);
}
/* Fill the socket address struct */
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(PORT);
inet_pton(AF_INET, "127.0.0.1", &remote_addr.sin_addr);
ZeroMemory(&(remote_addr.sin_zero), 8);
/* Try to connect the remote */
if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "ERROR: Failed to connect to the host! (errno = %d)\n", errno);
exit(1);
}
else
printf("[Client] Connected to server at port %d...ok!\n", PORT);
/* Send File to Server */
//if(!fork())
//{
char* fs_name = "/home/aryan/Desktop/quotidiani.txt";
char sdbuf[LENGTH];
printf("[Client] Sending %s to the Server... ", fs_name);
FILE *fs = NULL;
errno_t err = fopen_s(&fs, fs_name, "r");
if (fs == NULL)
{
printf("ERROR: File %s not found.\n", fs_name);
exit(1);
}
ZeroMemory(sdbuf, LENGTH);
int fs_block_sz;
while ((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0)
{
if (send(sockfd, sdbuf, fs_block_sz, 0) < 0)
{
fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", fs_name, errno);
break;
}
ZeroMemory(sdbuf, LENGTH);
}
printf("Ok File %s from Client was Sent!\n", fs_name);
//}
/* Receive File from Server */
printf("[Client] Receiveing file from Server and saving it as final.txt...");
char* fr_name = "/home/aryan/Desktop/progetto/final.txt";
FILE *fr = NULL;
err = fopen_s(&fr, fr_name, "a");
if (fr == NULL)
printf("File %s Cannot be opened.\n", fr_name);
else
{
ZeroMemory(revbuf, LENGTH);
int fr_block_sz = 0;
while ((fr_block_sz = recv(sockfd, revbuf, LENGTH, 0)) > 0)
{
int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);
if (write_sz < fr_block_sz)
{
error("File write failed.\n");
}
ZeroMemory(revbuf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512)
{
break;
}
}
if (fr_block_sz < 0)
{
if (errno == EAGAIN)
{
printf("recv() timed out.\n");
}
else
{
fprintf(stderr, "recv() failed due to errno = %d\n", errno);
}
}
printf("Ok received from server!\n");
fclose(fr);
}
//close(sockfd);
closesocket(sockfd);
printf("[Client] Connection lost.\n");
return (0);
}
Now you can compare and see what is the same and what is a bit different. Hope that helps you to understand.
In case, you wonder next, why you have linker errors: Link against ws2_32.lib. In contrast to unix systems, where sockets are part of "libc", sockets are factored out into a separate dll in windows.
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, ...);
Writing the C source below using Unix local sockets I got an error about the address already in use. After having checked man 7 Unix for further informations I tried to create a sub-folder where executing my program (obviously modifying the sun_path field on the current folder) but the error was ever the same.
Is there someone able to help me?
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#define MAXLEN 128
int main (int argc, char *argv[]){
struct sockaddr_un server;
int serverfd, clientfd;
socklen_t addrsize = sizeof(struct sockaddr_un);
char buff[MAXLEN], *path;
if (argc < 2){
printf("Error: %s [MESSAGE]\n", argv[0]);
return 1;
}
if ((serverfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
printf("Error \"%s\" in socket()\n", strerror(errno));
exit(1);
}
puts("socket()");
server.sun_family = AF_UNIX;
path = strcpy(server.sun_path, "/home/myhome/Dropbox/Sources/C/sub");
printf("[DEBUG]Address bound at %s\n", path);
if ((bind(serverfd, (struct sockaddr*)&server, addrsize)) < 0){
printf("Error \"%s\" in bind()\n", strerror(errno));
exit(1);
}
puts("bind()");
if ((listen(serverfd, 1)) < 0){
printf("Error \"%s\" in listen()\n", strerror(errno));
exit(1);
}
if ((clientfd = accept(serverfd, NULL, &addrsize)) < 0){
printf("Error \"%s\" in accept()\n", strerror(errno));
exit(1);
}
write(clientfd, argv[1], strlen(argv[1]));
read(clientfd, buff, sizeof(buff));
puts(buff);
close(clientfd);
close(serverfd);
return 0;
}
You should unlink() the path file before bind call. You will get this error when file exists during the bind. Either you should ensure to unlink/remove the file before exiting the application or you could always unlink it before bind.
Check man page of bind. Also, note the example given in the man page at the end.
You can try to use the SO_REUSEADDR flag like so:
int yes = 1;
if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
// error handling
exit(1);
}