LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 04-11-2013, 09:50 AM   #1
Brandon9000
Member
 
Registered: Apr 2012
Location: Florida
Distribution: Many
Posts: 111

Rep: Reputation: Disabled
Sockets - Prevent Partial Writes


I have written a socket client program in C++. At some point, I have to send data, and this is how I do it:

lenSent = write(serverSocket,sendBuf, len);

I can use send() instead of write(). It makes no difference to this question. I have set it to be non-blocking, because the thread must not get stuck. Unfortunately, it is connecting to a server which exits if I do a partial write to the socket.

How can I prevent a non-blocking socket from doing a partial write? Is there some way to poll it and make sure that it can handle the number of bytes I wish to send?

Thanks.

Brandon
 
Old 04-11-2013, 11:20 AM   #2
manu-tm
Member
 
Registered: May 2008
Location: France
Distribution: Ubuntu, Debian
Posts: 343

Rep: Reputation: 43
For that, you can use 'select'. You will find useful info in manpages:
Code:
man send
Also:
http://beej.us/guide/bgnet/output/ht...age/index.html
http://beej.us/guide/bgnet/output/ht...ed.html#select
 
Old 04-11-2013, 11:57 AM   #3
Brandon9000
Member
 
Registered: Apr 2012
Location: Florida
Distribution: Many
Posts: 111

Original Poster
Rep: Reputation: Disabled
The man page for send says:

"The select(2) call may be used to determine when it is possible to send more data."

This isn't really enough for me to know how to do it. I have never used select before.
 
Old 04-11-2013, 01:57 PM   #4
manu-tm
Member
 
Registered: May 2008
Location: France
Distribution: Ubuntu, Debian
Posts: 343

Rep: Reputation: 43
Have you read this: http://beej.us/guide/bgnet/output/ht...d.html#sendall ?

Here is an example:

Code:
/*
 * send_full() - Socket must be opened in non-blocking mode
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>

#define SEND_RECV_TIMEOUT_SEC	1
#define SEND_RECV_TIMEOUT_USEC	0

enum {
	SELECT_ERROR,
	SELECT_TIMED_OUT,
	SELECT_TRUE,
	SELECT_FALSE
};

int writable_data_is_available_on_socket(int sck)
{
	fd_set		write_set;
	struct timeval	timeout;
	int		i;

	FD_ZERO(&write_set);
	FD_SET(sck, &write_set);
	timeout.tv_sec = SEND_RECV_TIMEOUT_SEC;
	timeout.tv_usec = SEND_RECV_TIMEOUT_USEC;
	if ((i = select(sck + 1, NULL, &write_set, NULL, &timeout)) == -1) {
		fprintf(stderr, "select() error: %s\n", strerror(errno));
		fflush(stderr);
		return SELECT_ERROR;
	} else if (i == 0) {
		return SELECT_TIMED_OUT;
	} else {
		if (FD_ISSET(sck, &write_set))
			return SELECT_TRUE;
		else
			return SELECT_FALSE;
	}
}

/*
 * Return n bytes sent or -1 if error (connection closed by server or ?)
 */
int send_full(int sck, const char *str)
{
	int	len = strlen(str), i, j = 0;

	while (writable_data_is_available_on_socket(sck) == SELECT_TRUE) {
		if ((i = send(sck, str + j, len, 0)) != -1) {
			if (i > 0) {
				j += i;
				len -= i;
				if (len == 0)
					break;
			}
		} else {
			j = -1;
			if (errno == EPIPE) {
				fprintf(stderr, "Connection closed by server\n");
				fflush(stderr);
			} else {
				fprintf(stderr, "send() error: %s\n", strerror(errno));
				fflush(stderr);
			}
			break;
		}
	}
	return j;
}
 
Old 04-11-2013, 02:01 PM   #5
Brandon9000
Member
 
Registered: Apr 2012
Location: Florida
Distribution: Many
Posts: 111

Original Poster
Rep: Reputation: Disabled
Thanks! Does select do the write itself?
 
Old 04-11-2013, 02:17 PM   #6
manu-tm
Member
 
Registered: May 2008
Location: France
Distribution: Ubuntu, Debian
Posts: 343

Rep: Reputation: 43
Quote:
Originally Posted by Brandon9000 View Post
Thanks! Does select do the write itself?
No, you should use send_full() instead of write() inside your code.
 
Old 04-11-2013, 02:36 PM   #7
Brandon9000
Member
 
Registered: Apr 2012
Location: Florida
Distribution: Many
Posts: 111

Original Poster
Rep: Reputation: Disabled
Thanks again. I am also experimenting with checking to see how many unsent bytes are in the socket's internal buffer and waiting until it reaches zero with:

int error, value;
for (.....value > 0.....)
error = ioctl(serverSocket, SIOCOUTQ, &value);

Brandon
 
  


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
How prevent lighttpd sharing persistent sockets for different requests arm embedded golden_boy615 Linux - Embedded & Single-board computer 0 04-03-2012 06:21 AM
How to prevent lighttpd and fastCGI to share persistent sockets for different session golden_boy615 Programming 2 03-02-2012 01:11 AM
Prevent stealing of sockets raghu2383 Linux - Networking 2 09-20-2008 02:34 PM
Program to forward tcp sockets to unix domain sockets mikepol Linux - Networking 0 09-27-2007 09:49 AM
Partial Internet jrcreasy Linux - Networking 5 08-20-2005 12:07 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 09:41 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