Reputation: 3423
I wrote the following code in order to make an echo server (data I write to stdout
moves from my PC to server and back to my PC). The problem is that echo is not getting displayed on client's terminal. There are 2 server.cpp
processes running so I know that my connection has been accepted by the server. Tthe full code is here so that you can directly copy and run the code. The relevant parts of code are:
void reflect(int x)
{
int n;
int m;
char data[100];
cout<<"Entered reflect function"<<endl; //this gets displayed
n=read(x,data, 100); //***execution is not going beyond this point i.e. read is blocking***
cout<<"Client sent "<<n<<endl; //this doesn't get displayed
if(n>0)
{
while(n>0)
{
m=write(x,data,n);
n=n-m;
}
cout<<"Successfully echoed back to client"<<endl; //this doesn't get displayed
}
}
int main()
{
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));
int servfd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int x;
x=bind(servfd, (sockaddr*)(&serv), sizeof(serv));
cout<<"Bind returned"<<x<<endl; //this displays x as 0
listen(servfd, 5);
sockaddr cli;
int connfd;
pid_t id=-1;
socklen_t siz=sizeof(cli);
for(;;)
{
if(connfd=accept(servfd, &cli, &siz)>=0)
id=fork();
if(id==0)
reflect(connfd);
else
continue;
}
}
int main()
{
int clifd;
clifd=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));
connect(clifd, (sockaddr*)(&serv), sizeof(serv));//blocking call
int n,m;
char data[100];
char recvd[100];
for(;;)
{
fgets(data, 100,stdin );
n=strlen(data);
cout<<"You have written "<<n<<endl; //this returns the correct value
if(n>0)
{
while(n>0)
{
m=write(clifd,data,n);
n=n-m;
}
}
n=read(clifd, recvd, 100);
cout<<"Server echoed back "<<n<<endl; //this doesn't get displayed
if(n>0)
{
while(n>0)
{
m=fputs(data,stdout);
fflush(stdout);
n=n-m;
}
//cout<<data<<endl;
}
}
}
Upvotes: 1
Views: 5398
Reputation: 70971
Are you sure, you are inputting 100 characters on the client side via stdin
?
If not, you are writing less then 100 characters to the server, but the server expects 100 characters, so the server side read()
blocks.
You might solve this by modifying the client code like so:
while (n > 0)
{
m = write(clifd, data, sizeof(data));
...
A different approach whould be to split the client->server communication into two part:
1 Send the size of data to be echoed
2 Send the data itself
By doing so you allow the server to adjust the number of characters to read and then echo back.
This construct below does not make sense as long you do not check the value returned by write()
to be -1
.
The call to write()
will block until n
bytes are written or will return -1
on error. The latter will brake your logic.
while (n > 0)
{
m=write(fd, data, n);
n = n - m;
}
You might like to try something like this:
while (n > 0)
{
m = write(fd, data, n);
if (0 < m)
n = n - m;
else if (errno)
perror("write()");
}
This issue applies to the server as also to the client.
Upvotes: 1
Reputation: 2232
You are calling accept
in server.cpp with invalid arguments. The third argument must contain the size of the structure pointed by the second argument:
socklen_t siz = sizeof(cli);
for(;;)
{
if((connfd=accept(servfd, &cli, &siz))>=0)
...
Upvotes: 1
Reputation: 168716
In server.c, replace this incorrect line:
if( connfd=accept(servfd, &cli, &siz) >=0 )
with this correct one:
if( (connfd=accept(servfd, &cli, &siz)) >=0 )
serv.cc: In function ‘int main()’:
serv.cc:45:43: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
I try to always use -Wall -Werror
when compiling with g++ or gcc.
Upvotes: 3
Reputation: 1809
Some indentation would be nice but i also recommend you to re-write it with a check on differents function like said "mathematician1975".
You can fin lots of example on google. and also one in man accept
.
I recommand you to take a look at : poll
or select
to avoid the fork
Upvotes: 0