LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-07-2011, 11:32 AM   #1
lodup29
LQ Newbie
 
Registered: Mar 2010
Posts: 1

Rep: Reputation: 0
Non blocking socket send


Been trying all sorts of different things to implement a non-blocking send on a TCP server socket :

fcntl(lClientSocket, F_SETFL, O_NONBLOCK);
fcntl(lServerSocket, F_SETFL, O_NONBLOCK);
send(lClientSocket, lSendBuffer, lFrameLength, MSG_DONTWAIT);

As I kill the client, the server keeps blocking on the send no matter what. Am I missing something? Any other way to do that without involving any additional thread?
 
Old 03-07-2011, 01:06 PM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Without seeing specific code, it is hard to determine if you are setting the "correct" socket, on the server side, to be non-blocking. Each server always has a listen-socket, and then one or more client sockets.

Make sure that after a client connects, that you set its socket to be non-blocking; not the listen-socket. For example,

Code:
int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

/* call bind() listener to a port/address */

/* listen() for listener */

int client = accept(listener, NULL, NULL);

if (client > 0)
{
   /* fcntl() for the client socket */

   /* recv() from and send() data to the client */
}
Beware that once you set the socket to be non-blocking, that functions such as recv() may return an error of -1, with errno set to EAGAIN (EWOULDBLOCK). Unless you like checking for this error often, I would recommend that you setup a call to select() to determine when there is data to be received. Also, it may take a couple of calls to send() to determine that the client is no longer connected!
 
Old 03-07-2011, 07:24 PM   #3
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
In addition, you shouldn't be using the code you've shown us if you want to set O_NONBLOCK. There are two reasons for this.
  1. Whenever you do any system call, including the ones you show us, you should always check the returned value from the call to see whether there was an error.
  2. When you say:
    Code:
    fcntl(something,F_SETFL,O_NONBLOCK);
    you're not just turning on the O_NONBLOCK flag (assuming you're not getting an error return from the F_SETFL); you're also turning off any other flags which might be on. Unless you know what all those other flags are, and know either that they're not on already (a dangerous assumption) or you specifically want them off, you need to do this differently. First, use F_GETFL to get the flags (again checking for an error return); then OR in the O_NONBLOCK flag; then use F_SETFL to set the result.
Lookee here:
Code:
int flags;

flags=fcntl(something,F_GETFL,0);

if(flags<0)
{
  /* error handling code goes here */
}

flags |= O_NONBLOCK;

if(fcntl(something,F_SETFL,flags)<0)
{
  /* error handling code goes here */
}
 
Old 03-08-2011, 12:06 AM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I've had similar problems with connect and accept in non-blocking mode for inet sockets. I think it has to do with the routing, but I'm not really sure.
Kevin Barry
 
Old 03-08-2011, 06:04 AM   #5
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Originally Posted by ta0kira View Post
I've had similar problems with connect and accept in non-blocking mode for inet sockets. I think it has to do with the routing, but I'm not really sure.
I've had no great problems with non-blocking sockets for TCP, and routing has never been either an issue or a clue to a solution for me. When making sockets nonblocking, I've learned (sometimes through pain) these rules of thumb:
  1. If you're going to make sockets nonblocking on the client side, make all sockets nonblocking on the client side. Same on the server side, but let this also include the accept()ing socket.
  2. Use a select() loop when you're using nonblocking sockets. Don't do any read()ing or write()ing or accept()ing with a socket unless the select() loop tells you that something can be done. An immediate connect() is ok, though it will probably return error EINPROGRESS, which you can ignore. You can also keep track of that and close the socket if you get impatient with how long it takes for the connection to complete and read() or write() to become doable. Yes, people actually have reasons to do this. I think poll() can be used instead of select(), but I've had no experience with that.
  3. Rebuild your file descriptor lists for the select() call every time, just before you do the select() call.
  4. In the writing file descriptor list, include only those file descriptors for which there is data you want to send out at this time. Don't bother with the exception file descriptor list. Let that parameter to select() be NULL.
  5. It's time to do an accept() when, and only when, the select() loop tells you that you can read() on that socket. Sounds silly, but it's true.
  6. If a call to select() tells you that both reading and writing can be done, do the reading first.
  7. As mentioned previously in this thread, check your results for every call involving a socket. No exceptions.
  8. If you get an error return on write() and errno is EPIPE, or if you get a result of 0 on a read(), this means that the other end has closed the connection one way or another. Close your socket and don't mention that file descriptor in future calls to select(), unless of course you get that file descriptor again as the result of a new socket() or accept() call.
  9. If you get an error return and errno is EINTR, don't worry about it. "Don't worry" means forget that call this time around, move on to the next thing that select() says you can do, and catch this one on the next time through your select() loop. If you get EINTR on the select() itself, restart the loop, including rebuilding the file descriptor lists.
  10. Disable the SIGPIPE signal. You're already handling that situation in a normal, controlled manner.

Last edited by wje_lq; 03-08-2011 at 06:20 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] blocking and non blocking TCP send/recv problem golden_boy615 Programming 5 12-27-2010 03:27 PM
blocking socket Vs non-blocking socket barunparichha Linux - Software 2 04-02-2010 07:38 AM
blocking socket Vs non-blocking socket barunparichha Linux - Software 3 03-31-2010 10:15 PM
socket blocking problem pervert Programming 4 05-21-2006 01:28 PM
C socket non-blocking bob66 Programming 1 03-13-2005 10:21 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:27 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration