[CLUE-Tech] Sockets and http question
Sean LeBlanc
seanleblanc at americanisp.net
Sun Dec 29 18:50:14 MST 2002
On 12-29 17:28, David Anselmi wrote:
> Sean LeBlanc wrote:
> >Does anyone have much experience with sockets and http? I'm having some
> >difficulties trying to figure out why my connection just hangs, but only on
> >certain sites.
> >
> >I can include the test code I'm using, if anyone thinks they might be able
> >to help. This is in C++, but it might be more of a http protocol problem.
>
> You can use ethereal to capture a session from your code and one from a
> browser to the same site (maybe lynx will make a cleaner capture). Then
> you can compare the sessions and see what's different.
>
> I could look at the code (I'm curious what it does) but I'm no expert on
> C or C++. For http, is there a library you can use to do all the
> protocol stuff? Perl et. al. have that, it's a shame if you have to
> write your own.
I'm building ethereal port right now - I tried capturing packets with
ettercap since I already had that, but I wasn't getting the stuff being sent
by Lynx, only what was returning - even though it says it is sniffing both.
I ran this: ettercap -Nzs 192.168.1.3 <remotehostip>, FWIW.
Well, here's the code:
There should be 3 files: server.h, server.cc and test.cc, along with the
Makefile. A "make tst" should make my test program that I've created to
narrow down the problem I've been having.
Run like this: ./tst www.google.com /
or
./tst www.allmusic.com /
Both of the above hang, but www.yahoo.com comes across just fine, among
others.
I'm about to try this in Perl, Python or Java, just to see if the problem is
there, too.
A little background: this code is from MLAC, which I wrote. Much of the code
comes from Spiffy's Audiogalaxy tool - he wrote the code that scrapes
freedb.org and allmusic.com's site for CD data, I just made some changes,
and utilize that data in a different way. I'm starting to think about
re-writing it so that it uses the "CDDB" protocol instead, but I don't want
to go ape just yet if I can make this work. In the long term, that's
definitely a better idea, since websites can (and do) change.
Makefile:
OBJ = main.o server.o stringproc.o \
web.o mp3tech.o common.o sort.o
OBJ2 = test.o server.o
G++ = g++
CXXFLAGS = -O6 -g
am: $(OBJ)
$(G++) -o mlac $(OBJ)
tst: $(OBJ2)
$(G++) -o tst $(OBJ2)
clean:
rm -f $(OBJ) mlac
####### test.cc########
#include "server.h"
main(int argc, char *argv[])
{
char msg[1024];
//sprintf(msg, "P=amg&uid=SEARCH&sql=%s&opt1=1&x=9&y=2", fixString(artist));
if (argc != 3)
{
printf("Incorrect usage.\n");
printf("Usage: %s servername path\n", argv[0]);
exit(-1);
}
class server *S = new class server(argv[1], 80);
S->send("GET %s HTTP/1.1\r\n", argv[2]);
//S->send("User-Agent: \r\n", AGENT);
S->send("Host: %s:80\r\n", argv[1]);
S->send("Accept: text/html, text/*\r\n");
S->send("Content-type: application/x-www-form-urlencoded\r\n");
S->send("\r\n\r\n");
while (S->isConnected())
{
char *sin = S->receive();
printf("%s", sin);
}
}
############### server.cc ################
include "server.h"
// Using a very large buffer because the code gets really
// confused if the buffer cuts off in the middle of a tag.
#define BUFSIZE 524288
// ***************** Server class ************************
server::server()
{
sockfd = -1; sockf = NULL;
}
server::server(char *host, int port)
{
sockfd = -1; sockf = NULL;
connectto(host, port);
}
server::~server()
{
fclose(sockf);
}
void
server::connectto(char *host, int port)
{
struct sockaddr_in peer;
struct hostent * hp;
// DNS
hp = gethostbyname(host);
if (!hp) return;
// Create server address data member
peer.sin_family = AF_INET; peer.sin_port = htons(port);
bcopy(hp->h_addr_list[0], (char *)&peer.sin_addr, hp->h_length);
// Create a socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// Connect socket to server
if (connect(sockfd, (struct sockaddr *)&peer, sizeof(peer)) == -1)
{
// Error in connection
close(sockfd);
return;
}
else
{
// Make file structure for easier I/O
sockf = fdopen(sockfd, "a+");
sockfd = fileno(sockf);
}
}
int
server::isConnected()
{
if (!sockf) return FALSE;
else return (!feof(sockf));
}
int
server::getSockFD()
{
return sockfd;
}
void
server::send(char *fmt, ...)
{
va_list ap;
fd_set fds;
char text[1024];
bzero(text, 1024);
va_start(ap, fmt);
vsprintf(text, fmt, ap);
va_end(ap);
FD_ZERO(&fds); FD_SET(sockfd, &fds);
select(sockfd+1, 0, &fds, 0, 0);
fprintf(sockf, "%s", text);
}
char *
server::receive()
{
char ret[BUFSIZE]; bzero(ret, BUFSIZE);
fgets(ret, BUFSIZE-1, sockf);
return strdup(ret);
}
int
server::download(char *fn)
{
char ret[BUFSIZE];
// Skip the header
fgets(ret, 1024, sockf);
while ( (!feof(sockf)) && (strlen(ret) > 2) )
{
if (strstr(ret, "404 Object Not Found"))
return -1;
fgets(ret, 1024, sockf);
}
FILE *outf = fopen(fn, "w");
int numread;
numread = fread(ret, 1, BUFSIZE, sockf);
while (numread > 0)
{
fwrite(ret, 1, numread, outf);
numread = fread(ret, 1, 2048, sockf);
}
fclose(outf);
return 0;
}
############## server.h ###########
class server
{
public:
server();
server(char *host, int port);
~server();
bash-2.05$ less server.h
#ifndef SERVER_H
#define SERVER_H
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <stdarg.h>
#include <netdb.h>
#include <unistd.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
class server
{
public:
server();
server(char *host, int port);
~server();
void connectto(char *host, int port);
int isConnected();
int getSockFD();
void send(char *fmt, ...);
char * receive();
int download(char *fn);
private:
int sockfd;
FILE * sockf;
};
#endif
--
Sean LeBlanc:seanleblanc at americanisp.net
http://users.americanisp.net/~seanleblanc/
Get MLAC at: http://sourceforge.net/projects/mlac/
Counting in octal is just like counting in decimal -- if you don't use your
thumbs.
-Tom Lehrer
More information about the clue-tech
mailing list