|
Home > Archive > Unix Programming > March 2007 > multiple tcp server and client execution with close problem
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
multiple tcp server and client execution with close problem
|
|
|
| Hi, I have a tcp/ip server and client program runs like this:
server side:
main:
loop multiple times
{
system("./MyServer");
}
In the MyServer executable code:
socket
ioctl blocking
bind
listen
while loop to accept
recv something
recv data
send other things
close
Client side:
loop multipe times
{
socket
ioctl blocking
while loop to connect
send something
send data
shutdown send
recv other things
close
}
The problem it has is after first finishing first loop with successful
operation on both server and client, server is waiting for client, and
client is waiting to successfully connect to server again. So both are
waiting without doing anything. This is due to the close function
cannot complete closing the socket level descriptor for client side
detected by perror (maybe server side as well). Is there a way to get
around this problem? I have read the unix faq and search thru
comp.unix.programmer, but found no better solution for my situation
( I tried with or without shutdown at the end, also tried
SO_REUSEADDR, SO_LINGER with no luck).
The server code is a stand-alone executable. It has to be spawned by
function system for multiple times. I cannot get the server on all the
time then. So I decided to connect to server for multiple times from
client side. Is there a way in algorithm to better solve this
situation?
Thanks in advance,
Ray
| |
| Barry Margolin 2007-03-17, 7:16 pm |
| In article <1174117981.427306.6030@y66g2000hsf.googlegroups.com>,
"Ray" <alienatsf@gmail.com> wrote:
> Hi, I have a tcp/ip server and client program runs like this:
>
> server side:
> main:
> loop multiple times
> {
> system("./MyServer");
> }
>
> In the MyServer executable code:
> socket
> ioctl blocking
> bind
> listen
> while loop to accept
> recv something
> recv data
> send other things
> close
>
>
> Client side:
> loop multipe times
> {
> socket
> ioctl blocking
> while loop to connect
> send something
> send data
> shutdown send
> recv other things
> close
> }
>
> The problem it has is after first finishing first loop with successful
> operation on both server and client, server is waiting for client, and
Why is the server still waiting for the client? When the client does
shutdown(fd, SHUT_WR), the server will read EOF, and it should stop
trying to read from the socket.
> client is waiting to successfully connect to server again. So both are
> waiting without doing anything. This is due to the close function
> cannot complete closing the socket level descriptor for client side
> detected by perror (maybe server side as well). Is there a way to get
> around this problem? I have read the unix faq and search thru
> comp.unix.programmer, but found no better solution for my situation
> ( I tried with or without shutdown at the end, also tried
> SO_REUSEADDR, SO_LINGER with no luck).
>
> The server code is a stand-alone executable. It has to be spawned by
> function system for multiple times. I cannot get the server on all the
> time then. So I decided to connect to server for multiple times from
> client side. Is there a way in algorithm to better solve this
> situation?
>
> Thanks in advance,
>
> Ray
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
|
| On Mar 17, 3:30 pm, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article <1174117981.427306.6...@y66g2000hsf.googlegroups.com>,
>
>
>
>
>
> "Ray" <aliena...@gmail.com> wrote:
>
>
>
>
>
> Why is theserverstill waiting for the client? When the client does
> shutdown(fd, SHUT_WR), theserverwill read EOF, and it should stop
> trying to read from the socket.
>
>
>
>
>
>
>
>
>
> --
> Barry Margolin, bar...@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -
The server is still waiting because there is another function calling
system() to execute server again after its previous use. It's like
when both the server and client finish transmission, the server turns
off power, then restart again. while the client never turns off but
doing a loop to reconnect to the server again for the next
transmission. The server behaves like this because the server app is
a given executable for other major process, like Monte Carlo process.
The tcp/ip is for updating data for that process.
Thanks in advance,
Ray
| |
| Barry Margolin 2007-03-18, 1:21 pm |
| In article <1174182884.213328.185370@y66g2000hsf.googlegroups.com>,
"Ray" <alienatsf@gmail.com> wrote:
> On Mar 17, 3:30 pm, Barry Margolin <bar...@alum.mit.edu> wrote:
[vbcol=seagreen]
>
> The server is still waiting because there is another function calling
> system() to execute server again after its previous use. It's like
> when both the server and client finish transmission, the server turns
> off power, then restart again. while the client never turns off but
> doing a loop to reconnect to the server again for the next
> transmission. The server behaves like this because the server app is
> a given executable for other major process, like Monte Carlo process.
> The tcp/ip is for updating data for that process.
I'm confused about which loop is hanging. Your description shows a loop
calling system("./MyServer"), but there's also a loop INSIDE MyServer
that you described with "while loop to accept".
So are you having problems with the accept loop, or just when the server
restarts with system()?
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
|
| Barry,
Sorry for the confusion. Ignore the loop for accept(). It's useless
for accept() after settting socket to blocking mode.
Okay, my scenario is like this:
server side:
main:
loop multiple times
{
system("./MyServer");
}
In the MyServer executable code:
socket
ioctl blocking
bind
listen
accept
recv something
recv data
send other things
close
Client side:
loop multipe times
{
socket
ioctl blocking
while loop to connect
send something
send data
shutdown send
recv other things
close
}
execute main to run server 3 times:
../main 3
waiting for client
execute client to run 3 times:
../client 3
so for the first loop run, main receive data from client and send back
data to client, and main close the server socket and reopen another
socket for waiting the next incoming client connect() call. meanwhile
upon finishing sending data to server and receiving data back from
server, client close socket and open another socket to connect to
server.
So here comes the problem, in the 2nd loop run, the main (that runs
the server) stops there waiting for the new client while client also
stops there waiting for the new server to connect to.
Any idea why?
Btw, I run both client and server on the same machine using 127.0.0.1
loopback address.
My code works smoothly in my Suse Linux 10.2, but has this problem on
Mac OS X. but Mac OS X is based on Unix. What is the problem?
Thanks
On Mar 18, 9:16 am, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article <1174182884.213328.185...@y66g2000hsf.googlegroups.com>,
>
>
>
>
>
> "Ray" <aliena...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
>
> I'm confused about which loop is hanging. Your description shows a loop
> calling system("./MyServer"), but there's also a loop INSIDE MyServer
> that you described with "while loop to accept".
>
> So are you having problems with the accept loop, or just when the server
> restarts with system()?
>
> --
> Barry Margolin, bar...@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***- Hide quoted text -
>
> - Show quoted text -
| |
| Barry Margolin 2007-03-20, 1:27 am |
| In article <1174337734.333437.249300@e1g2000hsg.googlegroups.com>,
"Ray" <alienatsf@gmail.com> wrote:
> Barry,
>
> Sorry for the confusion. Ignore the loop for accept(). It's useless
> for accept() after settting socket to blocking mode.
I didn't understand what you meant by "while loop to {accept,connect}".
I originally thought you meant:
while ((fd = accept(...)) != -1) {
interact with client
close(fd);
}
Now that you mention blocking vs. non-blocking, I understand what you
meant.
>
> Okay, my scenario is like this:
>
>
> server side:
> main:
> loop multiple times
> {
> system("./MyServer");
> }
>
>
> In the MyServer executable code:
> socket
> ioctl blocking
> bind
> listen
> accept
> recv something
> recv data
> send other things
> close
>
>
> Client side:
> loop multipe times
> {
> socket
> ioctl blocking
> while loop to connect
> send something
> send data
> shutdown send
> recv other things
> close
> }
>
>
> execute main to run server 3 times:
> ./main 3
> waiting for client
>
> execute client to run 3 times:
> ./client 3
>
> so for the first loop run, main receive data from client and send back
> data to client, and main close the server socket and reopen another
> socket for waiting the next incoming client connect() call. meanwhile
> upon finishing sending data to server and receiving data back from
> server, client close socket and open another socket to connect to
> server.
>
> So here comes the problem, in the 2nd loop run, the main (that runs
> the server) stops there waiting for the new client while client also
> stops there waiting for the new server to connect to.
> Any idea why?
Try closing the listening socket in the server as soon as accept()
returns. I suspect what's happening is that the client is opening the
2nd connection before the 1st server has exited. So it's connecting to
the original listening socket. But the server never calls accept() on
that socket again.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
|
| Barry,
I did have the close() call to close the listen socket right after
accept(). Let me post the code up here. the codes work smoothly on my
Linux suse 10.2 but not on Mac OS X. I also posted a thread in Mac
programmer, so far no reply yet.
As you can see in my code listed below, I even put SO_REUSEADDR,
SO_REUSEPORT, SO_LINGER on for both server and client. I also bind the
client to a port 23456 so that it won't send data to itself.
I will try splitting the client code into two parts as the one in the
server side. I guess the client will exit nicely if I use system() to
call it multiple times rather than doing a forloop within one
program.
Thanks Barry.
Ray
/*
* RunModel.c
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
int i;
int numCycle = atoi(argv[1]);
for (i = 0; i < numCycle; i++) {
system("./server");
}
return 0;
}
/*
* server.c
*/
#include <winsock2.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void server(void);
int main()
{
server();
sleep(5);
return 0;
}
void server(void)
{
int len, mode, byteRecv, byteSent;
int hostPort = 27015;
int tempSeed = 0;
int seed = 0;
int serverSock, clientSock;
struct sockaddr_in hostAddr, clientAddr;
/* Create server socket */
serverSock = socket(AF_INET, SOCK_STREAM, 0);
if (serverSock == -1) {
fprintf(stderr, "Error creating socket\n");
close(serverSock);
exit(1);
}
/* Set to blocking socket */
mode = 0;
if (-1 == ioctl(serverSock, FIONBIO, (int) &mode)) {
perror("Blocking mode");
close(serverSock);
exit(1);
}
mode = 1;
if (0 == setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &mode,
sizeof(int))) {
printf("Set SO_REUSEADDR: ON\n");
}
else {
perror("SO_REUSEADDR");
}
/* Host address information */
bzero((char *)&hostAddr, sizeof(hostAddr));
hostAddr.sin_family = AF_INET;
hostAddr.sin_addr.s_addr = INADDR_ANY;
//hostAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
hostAddr.sin_port = htons((u_short) hostPort);
/* Bind the server socket */
if (bind(serverSock, (struct sockaddr*)&hostAddr,
sizeof(hostAddr)) < 0) {
perror("bind");
close(serverSock);
exit(1);
}
/* Listen to incoming client socket*/
if (listen(serverSock, SOMAXCONN) < 0) {
perror("listen");
close(serverSock);
exit(1);
}
bzero((char*)&clientAddr, sizeof(clientAddr));
/* Accept incoming socket */
len = sizeof(clientAddr);
printf("Waiting client to connect...\n");
clientSock = accept(serverSock, (struct sockaddr*)&clientAddr,
(socklen_t*)&len);
/* close server socket */
close(serverSock);
printf("Connected with client %s:%d\n",
inet_ntoa(clientAddr.sin_addr), (int)ntohs(clientAddr.sin_port));
/* Receive seed from client */
byteRecv = recv(clientSock, (char*)&tempSeed, sizeof(int), 0);
if (byteRecv > 0) {
seed = ntohl(tempSeed);
printf("Running seed %d!\n", seed);
}
shutdown(clientSock, SHUT_RD);
/* seed gets imcremented and send back to client */
seed++;
tempSeed = htonl((u_long)seed);
byteSent = send(clientSock, (const char*)&tempSeed, sizeof(int),
0);
if (-1 == byteSent) {
fprintf(stderr, "Error sending back seed = %d\n", seed);
close(clientSock);
}
else {
printf("Done!\n");
}
close(clientSock);
}
/*
* client.c
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void client(int *);
int main(int argc, char *argv[])
{
int numCycle = 0;
int seed = 0;
int i;
if (argc != 3) {
printf("Must enter number of run and seed\n");
exit(1);
}
numCycle = atoi(argv[1]);
seed = atoi(argv[2]);
for (i = 0; i < numCycle; i++) {
client(&seed);
}
return 0;
}
void client(int *seed)
{
int mode, temp;
int sock = 0;
int connectStatus = 0;
struct sockaddr_in targetAddr, hostAddr;
struct linger lingOpts;
lingOpts.l_onoff = 1;
lingOpts.l_linger = 0;
//char *targetIP = "172.16.0.112";
char *targetIP = "127.0.0.1";
int targetPort = 27015;
/* Create socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
close(sock);
exit(1);
}
/* Set to blocking socket */
mode = 0;
if (ioctl(sock, FIONBIO, (int) &mode) < 0) {
perror("ioctl");
close(sock);
exit(1);
}
/* set to address reuseable */
mode = 1;
if (0 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const
void*)&mode, sizeof(int))) {
printf("Set SO_REUSEADDR: ON\n");
}
else {
perror("SO_REUSEADDR");
}
if
(setsockopt(sock,SOL_SOCKET,SO_LINGER,&lingOpts,sizeof(lingOpts))
== 0) {
printf("Set SO_LINGER: ON \n");
}
else {
perror("setsockopt.linger");
}
/* Host address information */
bzero((char*)&hostAddr, sizeof(hostAddr));
hostAddr.sin_family = AF_INET;
hostAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
hostAddr.sin_port = htons((u_short) 23456);
/* Bind the host socket */
if (bind(sock, (struct sockaddr*)&hostAddr, sizeof(hostAddr))
< 0) {
perror("bind");
close(sock);
exit(1);
}
/* Target address information */
bzero((char*)&targetAddr, sizeof(targetAddr));
targetAddr.sin_family = AF_INET;
targetAddr.sin_addr.s_addr = inet_addr(targetIP);
targetAddr.sin_port = htons((u_short) targetPort);
printf("Sending seed %d\n", *seed);
/* Connect to target */
do {
connectStatus = connect(sock, (struct sockaddr *)
&targetAddr,
sizeof(targetAddr));
} while (connectStatus < 0);
printf("Connected to server!\n");
temp = htonl((u_long)*seed);
if (send(sock, (const char*)&temp, sizeof(int), 0) < 0) {
perror("send");
close(sock);
}
/* shut down send */
shutdown(sock, SHUT_WR);
temp = 0;
if (recv(sock, (char *)&temp, sizeof(int), 0) < 0) {
perror("recv");
close(sock);
}
else {
*seed = ntohl((u_long)temp);
}
close(sock);
}
| |
|
| Forget it, I made it work. Indeed, the function connect() caused all
the problems. Thanks Barry.
|
|
|
|
|