LinuxQuestions.org
Help answer threads with 0 replies.
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 11-23-2004, 07:28 AM   #1
jnusa
Member
 
Registered: Jul 2004
Location: Denmark, Aarhus
Distribution: Ubuntu, Suse
Posts: 98

Rep: Reputation: 15
read socket problem (proxy server related)


I've moved the 'cheap http server problems...' into a new thread, because it wasn't really my thread

To sum up:

I'm coding a proxy server, and I'm having great difficulty reading the body, og a http request. I read once, and then read returns -1 (with errno: "Connection reset by peer). It only reads a fraktion of what it is supposed to do. I memset the buffer, it reads into, and I'm pretty sure, it's ok.

Here's the code:

Code:
int read_body(int fd, char *ptr, int length)
{	
	int	res = 0;
	int temp=1;
	int total = 0;

	if(ptr != NULL)
	{
		while(total < length )
		{	
			res = (read(fd, ptr+total, length));
			if(res != -1)
				total += res;
			if(res == 0)
			{	puts("\n\n\nBREAK 0!!!!\n\n\n");
				break;
			}
			if(res < 0)
			{	puts("\n\n\nBREAK -1!!!\n\n\n");
				break;
			}
			printf("\n Read: %d\tTotal read: %d\t Total length: %d\tfd: %d", res-temp, total, length, fd);
		}
		logit("\n", "content.log");
		logit(ptr, "content.log");
	}
	else 
		logit("\nEvt. malloc error -> no error handeling!", "system.log");	
	
      close(fd);
      return res;
}

Output in terminal:

Code:
Status-code: 200
strlen(obj->body_content): 5548
Read: 2381     Total read: 2382         Total length: 5548     fd: 5

BREAK -1!!!
 
strlen(obj->body_content): 5548
Request end


If I read relative small sites (e.g. www.hootmail.dk, 2999b), there's no problem. If I read larger sites (e.g. www.leog.net), it only reads a fraktion (in one read cycle) and returns -1 (in the second read cycle).

Does anyone have any experience or have encountered the same problem? Or am I doing somethink wrong? Any info is greatly appriciated.

/Jnusa

Last edited by jnusa; 11-23-2004 at 07:59 AM.
 
Old 11-23-2004, 08:35 AM   #2
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,990

Rep: Reputation: 67
The -1 does not mean that no data was read. From the manpage:
Quote:
POSIX allows a read that is interrupted after reading some data to return -1 (with errno set to EINTR) or to return the number of bytes already read.
Also, to determine the value of errno, are you setting it to 0 before the call to read(), or could it be related to another I/O routine?
 
Old 11-23-2004, 08:54 AM   #3
Cedrik
Senior Member
 
Registered: Jul 2004
Distribution: Slackware
Posts: 2,140

Rep: Reputation: 242Reputation: 242Reputation: 242
How do you open your socket ? Could you post the code that initialize fd ?
 
Old 11-23-2004, 09:13 AM   #4
jnusa
Member
 
Registered: Jul 2004
Location: Denmark, Aarhus
Distribution: Ubuntu, Suse
Posts: 98

Original Poster
Rep: Reputation: 15
No, i do not set errno = 0. Should I do this every time, I call a function that use errno?
Yes you're right about -1, not meaning that there's no more data. But I guess it means that there has been som kind of error (specified with errno).
Keep in mind, that I use the current filedescriptor to read the header og the server respons, and I'm having no problem there.

I pretty much followed the tutorial in "Internetworking with TCP/IP", by Comer:

Here's my code for opening my socket.

function call in main:

Code:
#define QLEN 32 //max connection queue length

int main(int argc, char *argv[])
{
 	char *service = "http";
        ....
	msock = passiveTCP(service, QLEN);
        ...
	
			
			
return 0;	
}
Function I call in main:

Code:
int passiveTCP(const char *service, int qlen){
	return passivesock(service, "tcp", qlen);
}

Code:
int passivesock(const char *service, const char *transport, int qlen)
/*
 * Arguments:
 *      service   - service associated with the desired port
 *      transport - transport protocol to use ("tcp" or "udp")
 *      qlen      - maximum server request queue length
 */
{
	struct servent	*pse;	/* pointer to service information entry	*/
	struct protoent *ppe;	/* pointer to protocol information entry*/
	struct sockaddr_in sin;	/* an Internet endpoint address		*/
	int	s, type;	/* socket descriptor and socket type	*/

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;

    /* Map service name to port number */
	if ( (pse = getservbyname(service, transport)) )
		sin.sin_port = htons(ntohs((unsigned short)pse->s_port)
			+ portbase);
	else if ((sin.sin_port=htons((unsigned short)atoi(service))) == 0)
		errexit("can't get \"%s\" service entry\n", service);

    /* Map protocol name to protocol number */
	if ( (ppe = getprotobyname(transport)) == 0)
		errexit("can't get \"%s\" protocol entry\n", transport);

    /* Use protocol to choose a socket type */
	if ( (strcmp(transport, "udp")) == 0)
		type = SOCK_DGRAM;
	else
		type = SOCK_STREAM;

    /* Allocate a socket */
	s = socket(PF_INET, type, ppe->p_proto);
	if (s < 0)
		errexit("can't create socket: %s\n", strerror(errno));

/*	int yes = 1;
	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
		puts("setsockopt SO_REUSEADDR");
*/	
	int status = 0;
	/* Bind the socket  - loop until port is ready/released*/
	while(status==0)
	{	
		if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
			status = 1;
		if(status == 0) { puts("*"); (void)sleep(2); }
		/*errexit("can't bind to %s port: %s\n", service,
			strerror(errno));*/	
	}
	
	if (type == SOCK_STREAM && listen(s, qlen) < 0)
		errexit("can't listen on %s port: %s\n", service,
			strerror(errno));
	return s;
}
 
Old 11-24-2004, 03:53 AM   #5
jnusa
Member
 
Registered: Jul 2004
Location: Denmark, Aarhus
Distribution: Ubuntu, Suse
Posts: 98

Original Poster
Rep: Reputation: 15
I've tried setting errno to zero
Code:
errno = 0;
But still no go. It only reads once, returns -1 with errno message "Connection reset by peer". Does any have other solution to try or I'm I the first to encounter this problem.?
 
Old 11-24-2004, 10:16 AM   #6
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
It looks like you're doing a read() to get the header, then you're calling read_body(), but there's a good chance the body was already read in with the header and you've just somehow discarded that buffer. Once the HTTP server is done sending you the stuff it closes the connection (Connection reset by peer).

My guess is that you're going to find a big chunk of the body in the buffer with the header.
 
Old 11-24-2004, 03:50 PM   #7
jnusa
Member
 
Registered: Jul 2004
Location: Denmark, Aarhus
Distribution: Ubuntu, Suse
Posts: 98

Original Poster
Rep: Reputation: 15
Yeah, Im reading the header first. Since I only read 1 char at a time (until I reach body - is determined by CRLFCRLC), I'm certain that I'm not reading anymore data, than the header info. Also I can see in the 1k-2k bytes of body that I do read, that it's the beginning of the body (all the meta tags html start tag and so on). I'm trying to debug, by module testing my functions, and so far they work fine (read_body anyway, and som of the socket functions). I'm very puzzled about this. I've tried rearranging the read_body function, so it's reads the body faster, to avoid a timeout in the socket buffer. That wasn't the either. I've also tried declaring the buffer variable inside read_body, to see if the buffer pointer was messed up... that wasn't the case. Is there any socket options, that only will allow on read, pr connection or something like that?
 
Old 11-24-2004, 04:32 PM   #8
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
Check out man select. You can add the socket to the read set.
 
Old 11-24-2004, 04:45 PM   #9
jnusa
Member
 
Registered: Jul 2004
Location: Denmark, Aarhus
Distribution: Ubuntu, Suse
Posts: 98

Original Poster
Rep: Reputation: 15
hmm... well I'm doing that before I read the reply, to be sure that data is being transmitted. After I'm sure that data is being transmitted, I read the header, look at content (body length, status code, host name ect), and read the body content.
My select code:

Code:
        int maxfd = fd_request + 1; 
	struct timeval tv;
	tv.tv_sec = 10;
	tv.tv_usec = 0;
	int i, res;
	http_headers http_obj;		
	http_headers *obj = &http_obj;
	fd_set fdset; 				//filedescriptor set		 
	FD_ZERO(&fdset);			//enables timeout
	FD_SET(fd_request, &fdset);	//
	
	if((res = select(maxfd, &fdset, NULL, NULL, &tv))<0)
		printf("\n###Error select: %s", strerror(errno));
	else if(res == 0)
		http_obj.status = -2;	//reply with error message to client.
	
	i = 0;
	if(FD_ISSET(fd_request, &fdset))
		if((i = read_reply(fd_request, &obj))<0)
			printf("\nError readback: %s", strerror(errno));
Should I also select on filedescriptor when reading the body? I've tried to keep on reading, even though read() returns 0 and -1, to see if there were delays in the transmission. Of course that wasn't it either.

Last edited by jnusa; 11-24-2004 at 04:52 PM.
 
Old 11-25-2004, 10:31 AM   #10
jnusa
Member
 
Registered: Jul 2004
Location: Denmark, Aarhus
Distribution: Ubuntu, Suse
Posts: 98

Original Poster
Rep: Reputation: 15
Problem solved

The reson for the problem was, that I was sending a request from the client, to the server. When I calculated the length of the request, it was 100-300kb indstead of 200-300b! This length would be used when sending the data to the server (via : int write(int fd, char *data, int size). This somehow corrupted the memory or something. When I fixed the length, I could read the file descriptor more than once. I have no rational explaination for this.

Scenario:

Code:
-> Make mastersocket, and wait for connection
<- connection made by client -> make slave socket and fork()
-> read request and read hostname. Make request socket and connect to host.
-> send request to host (webserver), with wrong size 
<- Read respons from server - total size e.g. 8500b:
                      ->Read once 2650b (200 status code, request succeded, and start of the webpage ok (<html><body>...))
                      ->Read second time -> return -1: errno =  "Connection reset by peer"
All the variables (except the request file descriptor), is initialized after the request is sent to the server. After I fixed the size of the request, in the parameter to write() everthing was working. Anyone have an explaination?

Last edited by jnusa; 11-25-2004 at 10:34 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
cannot read data at server socket, though client socket sends it jacques83 Linux - Networking 0 11-15-2005 02:58 PM
read socket adoyee Programming 3 02-26-2004 07:06 AM
For Squid (proxy server) gurus: FTP from browser with read-write-modify permission Zingaro2002 Linux - Software 5 11-24-2003 05:56 AM
C/ C++ socket programming question (proxy servers) juby Programming 4 09-30-2003 02:34 PM
proxy server problem chandan Programming 1 07-07-2003 06:44 AM


All times are GMT -5. The time now is 05:20 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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration