Question

problem with socket in server

Asked by: mitchguy

I have a server which allows a dedicated client to connect
and pass data back and forth. The server which I coded runs on Linux and the client an executable I didn't code, runs on windows. My problem is that when the server is stopped and restarted while the client is connected I sometimes have to wait about a minute before I can get them talking again by stopping both of them. I suspect that the socket is still alive and thinks a connection is still there until it times out or something. I close the server which is running as a thread by exiting a while loop when a ctrl-c key combination is pressed.
while(!quit), where quit is set to true when a ctrl-c
is pressed.
After I break the while loop condition, I've tried the following with no luck.

pthread_exit(0); the while no longer stops with this
or
exit(0); results in a segfault
or
close(socketFileDescriptor); has no effect

If I keep the server running and stop and start the client
it will reconnect but will no longer exchange data.

At this point I'm not sure if it's my code or the software I'm working with.

I have not set any socket options or have any code that removes sockets. I read that exit(0) should close all open file descriptors. The only thing I've used is
fcntl() to set the non_blocking option.

So I guess what my question comes down to is what is the proper way to gracefully shutdown a server running as a thread. Or have I tried the right things and the problem is not with my code?
Here is how I create the socket:

struct sockaddr_in server;
struct sockaddr_in client;
unsigned int serverDataLength, clientDataLength;
int serverSock_fd, client_fd;

serverSock_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(5000);
serverDataLength = sizeof(server);
bind(serverSock_fd,(struct sockaddr * )&server
,serverDataLength);
listen(serverSock_fd,1);
clientDataLength = sizeof(client);
client_fd = accept(serverSock_fd,(struct sockaddr * )&client,&clientDataLength);
int flag = fcntl(client_fd,F_GETFL,0);
fcntl(client_fd,F_SETFL, O_NONBLOCK|flag);



This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2002-04-30 at 15:33:25ID20295628
Tags

non_blocking

,

socket

,

accept

,

server

Topic

C++ Programming Language

Participating Experts
3
Points
150
Comments
16

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Structs & Sockets
    I want to write a struct to a socket and read it into an identical struct on the other end. How can I achieve this? It is a simple struct containing only two int vars and one long variable. I am using Solaris 2.5.1 and SOCK_STREAM/AF_INET sockets
  2. HTTP Keep-Alive Sample
    I've heared, it's possible - to open connection to some server, and get more than one URL without reopening socket for every HTTP transaction, something like s = connect(... //open connection olny once ssprintf(cBuf,... "...GET file1.html \r\n Connection: Keep-Alive... w...
  3. Socket problem
    can somebody help me with this: i'm trying to write a server/client application using socket but i can't seem to be able to get the client connected to the server.what am i doing wrong here ?? pls help. //server side SOCKET srv_sock,cli_sock; struct sockaddr_in srv_addr,cli_...
  4. Socket Struct Error
    I'm writing a client-Server application. The client must ask for a certain information of the server and the server-app will return the data. But how do I make this. I have tried to send a struct from the server to the client but the server will not detectd that there is a ne...
  5. Sizeof()
    if 'char *array' points to an array in dynamic memory, how can i find the size of the array? i know sizeof() doesnt work in this situation...
  6. how to use socket to send a struct ?
    i want to use socket to send a struct to the server i would like to use the msgsend() to send it or the sendto() or is it possible ?

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: jhancePosted on 2002-04-30 at 15:38:14ID: 6982193

Can I assume that you do not have access to the client code?

 

by: mitchguyPosted on 2002-04-30 at 15:56:42ID: 6982222

yeah I don't have any code for that. So I'm just trying to
make sure I get everything right on my end.

 

by: sevaPosted on 2002-04-30 at 23:01:12ID: 6982697

I think all you have to do on your end to terminate
gracefully is to close the client_fd.
This will initiate normal TCP connection termination sequence.
The client should call close on its end after
its "read" call returns 0.
if the client doesn't do this, then it's not your fault.

 

by: ambiencePosted on 2002-05-01 at 04:27:37ID: 6983066

>> I suspect that the socket is still alive and thinks a connection is still there until it times out or something

This usually happens when you set the SO_LINGER option.

Can you post the code where you are termination connections

 

by: mitchguyPosted on 2002-05-01 at 05:30:52ID: 6983163


Here is my termination connections

//server is a class
Server *object;
object = new Server();

I run this thread:

void *thread_func(void *arg){
object->startFileTransfer();
pthread_exit(0);
}

void Server::startFileTransfer(void){
while(!quit){
//processing code
}
close(serverSock_fd);
}

}

 

by: sevaPosted on 2002-05-01 at 11:26:56ID: 6984168

Another possibility is that the server cannot bind the socket because the address/port is still in use (because the old connection)
Try insert setsockopt with SO_REUSEADDR before bind()

const int     on = 1;

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void*)&on, sizeof(on));

 

by: ambiencePosted on 2002-05-01 at 20:37:47ID: 6985078

closesocket(client_fd); ?? anywhere ?

 

by: mitchguyPosted on 2002-05-02 at 08:29:07ID: 6986418

using:
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,(const void* &on, sizeof(on));
solved half of my problem.
With the client running continuously trying to connect with the server. I can start and stop the server at will and the client connects and I don't have to wait.

My only problem now is if the Server is continuously running and after the client connects I stop the client, the server crashes with the message "broken pipe"
so I can't stop and start the client with the Server Continuosly.
I do also have
closesocket(client_fd);
 

 

by: sevaPosted on 2002-05-02 at 09:49:33ID: 6986643

Can you post your code for the server with more details,
better all the server code?
From what is already there, it seems that you
are not calling accept inside the while loop.

 

by: mitchguyPosted on 2002-05-02 at 12:11:46ID: 6987046

I don't have my accept call in the while loop.
That is an obvious mistake on my part. I think I originally
put it in there and it wasn't working properly so I moved it out. After putting it back in the while loop it does
connect and disconnect with out crashing the server, but It
hangs before the accept call the second time through the
loop. So The processing stops.
createSocket(){
struct sockaddr_in server;
struct sockaddr_in client;
unsigned int serverDataLength, clientDataLength;
int serverSock_fd, client_fd;

serverSock_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(5000);
serverDataLength = sizeof(server);
bind(serverSock_fd,(struct sockaddr * )&server
,serverDataLength);
listen(serverSock_fd,1);
clientDataLength = sizeof(client);
}

startServer(){
 createSocket();
 
while(!quit){

client_fd = accept(serverSock_fd,(struct sockaddr * )&client,&clientDataLength);
int flag = fcntl(client_fd,F_GETFL,0);
fcntl(client_fd,F_SETFL, O_NONBLOCK|flag);
read(client_fd,&buf,sizeof(buf));
processMsg(buf);
}
}

 

by: sevaPosted on 2002-05-02 at 13:10:03ID: 6987183

Does your client follow request-response pattern,
creating a new connection for every data transfer?

Also, you set the socket to be non-blocking,
then, you need to handle all different cases for the read()
call, such as read() returns because it would block
(no data available), read() returns some data < sizeof(buf)
etc.
You need to somehow know how much data the client sends
and make another "while" loop around read() until the server reads that much data.
After you are done with the request, you need to close
client_fd at the end of the loop, before going back to
accept().

 

by: mitchguyPosted on 2002-05-02 at 13:30:22ID: 6987222

The connection is meant to stay active once made
until the session is over so a new connection is not
made for every data transfer.
For my program there is only one client that is
allowed to connect at any given time. Once the connection
is made the client starts sending messages of all types
and sizes each at different time intervals most at 4 per second, until the session is over.
The buffer is big enough to hold all messages that are
sent from the client for each read.

I've specified the socket to have allow one connection
at a time with listen(serverSock_fd,1); since there is only one possible client.

so once the client connects and I get my client
socket file descriptor I try to read that file
descriptor. It gets set from the return value
of accept.

what happens to the accept function call while
the client is connected the second time through the loop. Does it still get called
and reset the file Descriptor so my read call no
longer reads a valid file descriptor?

 

by: sevaPosted on 2002-05-02 at 14:04:59ID: 6987314

OK, then you need to move accept() before the "while".
accept() takes the first availble incoming TCP
connection and creates a new socket for it.

However, you still have a problem with not knowing
how much data the client sends. read() may return
-1 with errno==EWOULDBLOCK if there is no data available,
or it may return any number of bytes that is ready,
but not necessary all bytes that client sent.

 

by: mitchguyPosted on 2002-05-02 at 14:27:31ID: 6987348

It's true I don't know exactly how much data will
be there for any given read() and sometimes it was returning -1 , but it wasn't blocking.
I was printing out the bytes read and saw the -1
so I added this:
int bytes_read = read(...);
if (bytes_read > 0){
processMsg(buf);
}

I suppose the NON_BLOCKING flag allowed me to continue
reading.

So if I have the accept() outside of the while loop.
and the client disconnects and then trys to reconnect
,since I don't have an accept() call in the while loop
it should fail right?
If closing the file descriptor is what's necessary when the client disconnects, how can the server know when the
connection is closed.
I was thinking if I put the accept() call in the while loop
, but only called it when I know there isn't a connection
active.
something like the following.
bool connected = false;

if(!connected){
accept();
connected = true;
}

If I know when a connection is closed I could set connection = false;

Do you think this would work?
is there a way to know when the connection is closed?

 

 

by: sevaPosted on 2002-05-02 at 15:24:37ID: 6987452

A connection is closed when read() returns 0.
Also, you may want to check the errno when read()
returns -1.
If errno==EWOULDBLOCK, then it's fine since
read() returned because no data availble.
If errno != EWOULDBLOCK, then an error occured.

It may work, though in general it is not a good design.
Your server continuosly loops around wasting CPU time.
A better solution might be to use select().

 

by: mitchguyPosted on 2002-05-02 at 17:21:50ID: 6987589

I think you've given me enough information to solve all of
my problems tomorrow.
Thanks

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...