I am looking to download or read a file from a server over HTTPS, and I'm using openSSL for it.
I see the connection succeeds, however SSL_read() returns 0. SSL_get_error() returns 6 which refers to SSL_ERROR_ZERO_RETURN macro and seems to be a normal behavior but I'm not sure why was the connection shutdown while something was being read? And this might be why it's reading 0 bytes?
#define CHECK_NULL(x) if ((x)==NULL) exit (1)
#define CHECK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHECK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
void ServerConnectAndRcv(uint8_t *str)
{
int err;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
SSL* ssl;
char* str;
char buf [4096];
const SSL_METHOD *meth;
SSLeay_add_ssl_algorithms();
meth = TLSv1_2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth);
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
// create a socket and connect to the server
sd = socket (AF_INET, SOCK_STREAM, 0);
CHK_ERR(sd, "socket");
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr (<SERVER-IP>); /* Server IP */
sa.sin_port = htons (<SERVER-PORT>); /* Server Port number */
ssl = SSL_new (ctx);
CHECK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_connect (ssl);
CHECK_SSL(err);
// read from the server
err = SSL_read (ssl, buf, sizeof(buf) - 1);
CHECK_SSL(err);
if (err <= 0)
{
printf ("Error reading: %d\n", SSL_get_error(ssl, err));
}
buf[err] = '\0';
printf ("Received % bytes\n", err); // Received 0 bytes
SSL_shutdown (ssl);
}
As one of the commenters pointed out, I needed to send a GET request to be able to receive a response back from the server.
I sent pszResourcePath via SSL_write() and SSL_read() read the entire response just fine.
char pszRequest[100]= {0};
char pszResourcePath[]="<resourcePath>";
char pszHostAddress[]="<serverIP>";
sprintf(pszRequest, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Keep-Alive\r\n\r\n", pszResourcePath, pszHostAddress);
I have two c files, server and client. The server listens for and accepts a connection request from a client, and then it waits to print out a message given to it by the client. The connection process works perfectly, but I don't know how to get it to relay the message it's supposed to receive.
Since these two files are separate, I'm unsure what file descriptor to put into the write() call in the client. The read() call in the server is called before the write() call in the client, and it uses the file descriptor s2, which is the output from its accept() call.
How can I get the write() call in my client file to talk to the same socket that the read() call in my server file is looking for?
The code below has had some functions like error checking omitted in the interest of time.
Here is the content of my server.c file:
int main(int argc, char** argv) {
char buffer[257];
int pipe_fds;
int psts; // Holds result of pipe creation attempt
psts = my_pipe(pipe_fds);
if(psts == 0) { // If pipe is successful
printf(" SERVER: Server running...\n");
printf(" SERVER: Waiting for message...\n");
read(pipe_fds, buffer, 257); // <---------- Output stops here
printf(" SERVER: Message: %s\n", buffer);
close(pipe_fds);
}
return 0;
}
This is the function my_pipe() used in the above block:
int my_pipe(int fd) {
// SET UP CONNECTION REQUEST SOCKET: S1 -------------------------------------------
int s1 = socket(AF_UNIX, SOCK_STREAM, 0);
if(s1 == -1) {return -1;}
struct sockaddr name1 = {AF_UNIX, "ServerSocket"};
socklen_t namelen1 = sizeof(struct sockaddr) + 13;
bind(s1, &name1, namelen1);
printf("\n SERVER: [s1] Socket Created! \n");
// SET UP LISTEN/ACCEPT -----------------------------------------------------------
if(listen(s1, 1) == -1) {return -1;}
printf("\n SERVER: Server Listening! \n\n");
// SET UP CLIENT CONNECTION SOCKET: S2 --------------------------------------------
struct sockaddr name1_0;
socklen_t namelen1_0;
int s2 = accept(s1, &name1_0, &namelen1_0); // <----------- This is where s2 is defined
if(s2 == -1) {return -1;}
printf(" SERVER: Client Found...\n");
fd = s2;
close(s1);
return 0;
}
Lastly, this is the content of my client.c file:
int main(int argc, char** argv) {
char buffer[257];
// Create a socket to connect to the server with
int s0 = socket(AF_UNIX, SOCK_STREAM, 0);
if(s0 == -1) { return -1; }
// Create a sockaddr for the known existing socket "ServerSocket"
struct sockaddr server_name = {AF_UNIX, "ServerSocket"};
socklen_t server_len = sizeof(struct sockaddr) + 13;
// Connect to "ServerSocket"
if(connect(s0, &server_name, server_len) == -1) {return -1;}
printf("CLIENT: Client Connected!\n");
strcpy(buffer, "This is the Client Message.");
write([INSERT SERVER SOCKET FD], buffer, strlen(buffer) + 1); // <----- The line in question
printf("CLIENT: Message Sent!\n");
close(s0);
return 0;
}
The output of the server from running both files:
SERVER: [s1] Socket Created!
SERVER: Server Listening!
SERVER: Client Found...
SERVER: Server running...
SERVER: Waiting for message...
(infinite waiting)
Just some pseudo code for the common logic, that may be useful for the general understanding.
In simple words you setup the server first and the return from accept gives you the client socket.
So you have 2 different sockets. You dont need the server socket anymore and close the server socket, so it can accept further connections (only can accept one at a time). You can
take the client socket and pass it to either a function, or fork() or pass it to a thread - all up to you.
main () {
int server_socket;
server_socket = socket(AF_INET, ....);
init(addrinfo()) // initialize server_socket
bind //port
listen // set backlog queue, number of allowed waiting connections)
while (1) { //loop to wait for incoming connections
int client_socket = accept(server_socket....) //client connection !
close(server_socket); // otherwise blocked
my_pipe(&client_socket) /pass client socket to function
}
my_pipe(*socket) {
read/write //send/recv
close(socket);
}
I have spring-boot server that I am running in AWS. The server works fine. I can access it using chrome, postman, and curl with no issues. However, I have an embedded device that is running C and I am using sockets to try to connect to my server. The embedded device is running Linux so I can use curl to talk to the server with no issues. However, my C sockets code cannot seem to find the resource on the server. I keep getting 404's.
Here is my embedded client code,
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <errno.h>
int main() {
// Define some parameters
int sockfd, bytes_read;
struct sockaddr_in dest;
char buffer[4000];
char hdr[1000];
// Create Server Client Strings
bzero(hdr, sizeof(hdr));
strcpy(hdr, "GET /hello HTTP/1.1\r\n");
strcat(hdr, "Host: 52.200.39.81\r\n\r\n");
// Clean things up a bit before sarting
printf("\n\n");
// Create Socket
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
printf("Socket not created\n");
return 0;
}
// Initialize server address/port struct
bzero(&dest, sizeof(dest));
// *** Added this line to fix the code ***
dest.sin_addr.s_addr = inet_addr("52.200.39.81", &dest.sin_addr.s_addr);
dest.sin_family = AF_INET;
dest.sin_port = htons(8080);
if ( inet_addr("52.200.39.81", &dest.sin_addr.s_addr) == 0 ) {
printf("Incorrect Address Expression\n");
return 0;
}
// Connect Socket
if ( connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0 ) {
printf("Socket Connection Failed\n");
close(sockfd);
return 0;
}
// Send data
if (send(sockfd, hdr, strlen(hdr), 0) < 0) {
printf("Send Data Failed\n");
return 0;
}
printf("Socket successfully sent\n");
printf("\nSend Message - TxBufferSize = %d\n\n",strlen(hdr));
printf("%s", hdr);
bzero(buffer, sizeof(buffer));
bytes_read = recv(sockfd, buffer, sizeof(buffer), 0);
if (bytes_read < 0) {
printf("Read Data Failed\n");
}
if (bytes_read > 0) {
// Print out receive buffer
printf("\n\nReceived Message -- RxSize = %d \n\n", strlen(buffer));
printf("%s", buffer);
}
if (bytes_read == 0) {
printf("No Read Bytes Received\n");
}
/*---Clean up---*/
close(sockfd);
return 0;
}
Here is what I get back,
debian#beaglebone:~$ ./helloworld
Socket successfully sent
***** Send Message -- TxBufferSize = 80 *****
GET http://52.200.39.81:8080/hello HTTP/1.1
Host: 52.200.39.81
accept: */*
***** Received Message -- RxBufferSize = 467 *****
HTTP/1.1 404 Not Found
Date: Sat, 02 Apr 2016 17:36:37 GMT
Server: Apache/2.2.22 (Debian)
Vary: Accept-Encoding
Content-Length: 283
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /hello was not found on this server.</p>
<hr>
<address>Apache/2.2.22 (Debian) Server at 52.200.39.81 Port 8080</address>
</body></html>
debian#beaglebone:~$
If I use the curl command on the embedded device,
debian#beaglebone:~$ curl 52.200.39.81:8080/hello
Greetings WebServiceTest1 -- ServiceCount = 11
debian#beaglebone:~$
I get the correct response from the server. So I am confident that the embedded device is talking to my server. Just can't seem to get the sockets code to work. Any help would be appreciated.
Ok, I found out what the problem was. I did not set the socket address. A very simple omission but that what the problem was. I have updated the code and it is now working. I added gethostbyname to make the code more standardized. The new lines of code are in the comment section "// Initialize server address/port struct". I would like to thank Lilas for providing me the reference code that led me to the omission of the dest.sin_addr.s_addr line. Below is the corrected code.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
int main() {
// Define some parameters
int sockfd, bytes_read;
struct sockaddr_in dest;
char *hostname = "skmdev1.net";
struct hostent *hostent;
char buffer[4000];
char hdr[1000];
// Create Server Client Strings
bzero(hdr, sizeof(hdr));
strcpy(hdr, "GET /hello HTTP/1.1\r\n");
strcat(hdr, "Host: skmdev1.net\r\n\r\n");
// Clean things up a bit before sarting
printf("\n\n");
// Build the address
hostent = gethostbyname(hostname);
if (hostent == NULL) {
printf("error: gethostbyname(\"%s\")\n", hostname);
return 0;
}
// Create Socket
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
printf("Socket not created\n");
return 0;
}
// Initialize server address/port struct
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(8080);
dest.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*)hostent->h_addr));
if ( dest.sin_addr.s_addr == INADDR_NONE ) {
printf("Incorrect Address Expression\n");
return 0;
}
// Connect Socket
if ( connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0 ) {
printf("Socket Connection Failed\n");
close(sockfd);
return 0;
}
// Send data
if (send(sockfd, hdr, strlen(hdr), 0) < 0) {
printf("Send Data Failed\n");
return 0;
}
printf("Socket successfully sent\n");
printf("\nSend Message - TxBufferSize = %d\n\n",strlen(hdr));
printf("%s", hdr);
bzero(buffer, sizeof(buffer));
bytes_read = recv(sockfd, buffer, sizeof(buffer), 0);
if (bytes_read < 0) {
printf("Read Data Failed\n");
}
if (bytes_read > 0) {
// Print out receive buffer
printf("\n\nReceived Message -- RxSize = %d \n\n", strlen(buffer));
printf("%s\n\n", buffer);
}
if (bytes_read == 0) {
printf("No Read Bytes Received\n");
}
/*---Clean up---*/
close(sockfd);
return 0;
}
I'm writing a Minecraft Classic Server in C using TCP sockets in Winsock and I'm writing the function to perform a 'heartbeat', just an HTTP request which should return a URL to me - no headers or HTML at all.
It sends the data to Minecraft.net (at least it says it does) but it just sits there for a few minutes after that and eventually tells me that it got no data from minecraft.net, ie it reads "HeartBeat: Recieved no data from minecraft.net"
I have the following code so far (excluding WSAStartup etc.):
void HeartBeat()
{
unsigned int clSock;
struct hostent *host;
struct sockaddr_in server_addr;
char buffer[128] = "";
char request[256] = "GET /"; //(I will not show the rest of the request...)
if((clSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("HeartBeat: Error creating socket\n");
return;
} else {
printf("HeartBeat: Success in creating socket\n");
}
printf("HeartBeat: Resolving hostname 'www.minecraft.net'... ");
if((host = gethostbyname("www.minecraft.net")) == NULL)
{
printf("failed\n");
return;
} else {
printf("success!\n");
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
server_addr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if (connect(clSock, (SOCKADDR*) &server_addr, sizeof(server_addr)) == SOCKET_ERROR)
{
printf("HeartBeat: Error conneting to www.minecraft.net\n");
return;
} else {
printf("HeartBeat: Connected to www.minecraft.net\n");
}
if (send(clSock, request, sizeof(request), 0) < 0)
{
printf("HeartBeat: Sending data failed.\n");
closesocket(clSock);
return;
} else {
printf("HeartBeat: Success in sending data.\n");
}
if ((recv(clSock, buffer, sizeof(buffer), 0)) == 0)
{
printf("HeartBeat: Received no data from www.minecraft.net\n");
closesocket(clSock);
return;
} else {
printf("HeartBeat: Yay, success! Url is '%s'", buffer);
closesocket(clSock);
return;
}
}
Could someone please point out where I've gone wrong? Thanks a million.
You're not sending an HTTP request.
A (minimal) HTTP request would have to be at least the string:
char request[256] ="GET / HTTP/1.0\r\n\r\n";
Or in the case of HTTP 0.9:
char request[256] ="GET /\r\n\r\n";
You must send just that string, not the whole request buffer containing a lot of 0 bytes, so do:
send(clSock, request, strlen(request), 0)
You are doing just 1 recv() call, that might not read the entire response. You're supposed to read until the connection closes (until recv() returns 0). Or to really follow the HTTP protocol, you need to parse the response, look for a Content-Length header. Read all the headers, then read the number of bytes in the body (if any). To really cope with all the minute details of HTTP, you really need a HTTP library though.
I want to map two ports (anything goes to port x goes to port y and visa versa )with a C program, I wrote this program but it does not work.
This is my code:
int recv_all_nonblock(int sockfd,char* buff,int buffersize)
{
int numbytes;
if ((numbytes = recv(sockfd, buff, buffersize-1, MSG_NOSIGNAL|MSG_DONTWAIT)) <= 0)
{
perror("recv");
}
else if( numbytes>0)
{
buff[numbytes] = '\0';
}
return numbytes;
}
int sendall(int sockfd, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n=0;
while(total < *len)
{
n = send(sockfd, buf+total, bytesleft, MSG_NOSIGNAL|MSG_DONTWAIT);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
int Connect_To_Remote(char *Addr,char* PORT)
{
int sockfd;
struct addrinfo hints, *servinfo=NULL, *p=NULL;
int rv;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
while (p==NULL)
{
sleep(5);
while((rv = getaddrinfo(Addr, PORT, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
sleep(5);
}
for(p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
{
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL)
{
fprintf(stderr, "client: failed to connect\n");
}
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
return sockfd;
}
int recv_all(int sockfd,char* buff,int buffersize)
{
int numbytes;
fd_set readfd_set;
struct timeval recvwait;
recvwait.tv_sec=10;
recvwait.tv_usec=0;
FD_ZERO(&readfd_set);
FD_SET(sockfd, &readfd_set);
if(select(sockfd+1, &readfd_set, NULL, NULL, &recvwait) <= 0)
{
perror("wait for recieve error:");
}
else
{
if ((numbytes = recv(sockfd, buff, buffersize-1, MSG_NOSIGNAL|MSG_DONTWAIT)) == -1)
{
perror("recv");
}
else if( numbytes>0)
{
buff[numbytes] = '\0';
}
return numbytes;
}
return 0;
}
void *Port_Mapper()
{
int sockfd,newfd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *tmpaddrinfo;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
int rv;
int yes=1;
int ret=0;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
while (1)
{
if ((rv = getaddrinfo(NULL, MapPort, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
sleep(2);
}
else
{
break;
}
}
while (1)
{
for(tmpaddrinfo = servinfo; tmpaddrinfo != NULL; tmpaddrinfo = tmpaddrinfo->ai_next)
{
if ((sockfd = socket(tmpaddrinfo->ai_family,tmpaddrinfo->ai_socktype,tmpaddrinfo->ai_protocol)) == -1)
{
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
if (bind(sockfd, tmpaddrinfo->ai_addr, tmpaddrinfo->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (tmpaddrinfo == NULL)
{
fprintf(stderr, "server: failed to bind\n");
sleep(1);
}
else
{
break;
}
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, MAXLISTENQ) == -1)
{
perror("listen");
exit(1);
}
int bufpoint=0;
printf("server: waiting for connections...\n");
while(1)
{ // main accept() loop
char buff[MAX_SOCK_BUFFER];
char buff2[MAX_SOCK_BUFFER];
ret=0;
int sockfdweb=0;
sin_size = sizeof (their_addr);
printf("mapping server: going to accept connections...\n");
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
printf("\n\nmapping server: connections accepted:%d\n",newfd);
sockfdweb=Connect_To_Remote("192.168.1.10","80");
if (sockfdweb<0)
{
printf("can not connect to %s\n","192.168.1.10");
break;
}
while(1)
{
memset(buff,0,sizeof(buff));
ret=recv_all_nonblock(newfd,buff,MAX_SOCK_BUFFER);
printf("recved from client1,%d\n",ret);
if (ret<=0)
{
perror("recieve error from browser:");
close(newfd);
sin_size = sizeof (their_addr);
printf("mapping server: going to accept connections...\n");
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
ret=recv_all_nonblock(newfd,buff,MAX_SOCK_BUFFER);
printf("recved from client10,%d\n",ret);
if (ret<=0)
{
perror("recieve error from browser:");
close(newfd);
sin_size = sizeof (their_addr);
printf("mapping server: going to accept connections...\n");
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
}
else if(ret>0)
{
printf("recved from client0\n");
printf("%s\n",buff);
if (sendall(sockfdweb,buff,&bufpoint)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to 80,0\n");
}
}
else if(ret>0)
{
printf("recved from client\n");
printf("%s\n",buff);
if (sendall(sockfdweb,buff,&bufpoint)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to 80\n");
}
memset(buff2,0,sizeof(buff2));
ret=recv_all_nonblock(sockfdweb,buff2,MAX_SOCK_BUFFER);
printf("recv from 80...%d\n",ret);
if (ret<=0)
{
close(sockfdweb);
sockfdweb=Connect_To_Remote("192.168.1.10","80");
if (sockfdweb<0)
{
printf("can not connect to %s\n","192.168.1.10");
break;
}
ret=recv_all_nonblock(sockfdweb,buff2,MAX_SOCK_BUFFER);
printf("recv from 80.9..%d\n",ret);
if (ret<=0)
{
close(sockfdweb);
sockfdweb=Connect_To_Remote("192.168.1.10","80");
if (sockfdweb<0)
{
printf("can not connect to %s\n","192.168.1.10");
break;
}
}
else if (ret>0)
{
printf("recved from 809\n");
if (sendall(newfd,buff2,&ret)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to client9\n");
}
}
else if (ret>0)
{
printf("recved from 80\n");
if (sendall(newfd,buff2,&ret)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to client\n");
}
}
}
return 0;
}
int main()
{
.
.
.
.
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&portmapper_threadid,&attr,Port_Mapper,NULL);
pthread_attr_destroy (&attr);
.
.
.
.
}
I putted some "printf" in Port_Mapper function and made some changes to trace what happens when I request a web in my browser like this:
http://127.0.0.1:8090/
and the program out put of refreshing two or three times of browser is this:
mapping server: connections accepted:5
client: connecting to 192.168.1.10
recved from client1,360
recved from client
GET /1/ HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Cache-Control: max-age=0
send to 80
recv: Resource temporarily unavailable
recv from 80...-1
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recv from 80.9..-1
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recved from client1,-1
recieve error from browser:: Resource temporarily unavailable
mapping server: going to accept connections...
recved from client10,360
recved from client0
GET /1/ HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Cache-Control: max-age=0
send to 80,0
recv: Resource temporarily unavailable
recv from 80...0
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recv from 80.9..-1
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recved from client1,-1
recieve error from browser:: Resource temporarily unavailable
mapping server: going to accept connections...
recv: Resource temporarily unavailable
recved from client10,-1
recieve error from browser:: Resource temporarily unavailable
mapping server: going to accept connections...
recv: Resource temporarily unavailable
recv from 80...0
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recv from 80.9..-1
client: connecting to 192.168.1.10
recved from client1,332
recved from client
GET / HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
send to 80
recv: Resource temporarily unavailable
recv from 80...-1
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recv from 80.9..-1
client: connecting to 192.168.1.10
recv: Resource temporarily unavailable
recved from client1,-1
recieve error from browser:: Resource temporarily unavailable
mapping server: going to accept connections...
as you can see the program receive data from browser correctly but when it sends the data to webserver and wants to receive data from web server it always gets error and does not receive any data from web server:
send to 80
recv: Resource temporarily unavailable
recv from 80...-1
I have to say that the web server works correctly with no problem.
Can any body tell me what is my problem????
Your code is much to complicated for such an easy task. It can be simplified quote a lot, see this (pseudo) code:
void mapper()
{
int server_socket = create_server_socket();
for (;;)
{
int incomming_socket = accept(server_socket);
int web_server_socket = connect_to_webserver();
make_socket_nonblocking(incomming_socket);
make_socket_nonblocking(web_server_socket);
for (;;)
{
int disconnected = 0;
FD_ZERO(&read_set);
FD_SET(incomming_socket, &read_set);
FD_SET(web_server_socket, &read_set);
select(max_socket + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(incomming_socket, &read_set))
{
disonnected = recv_and_send(incomming_socket, web_server_socket);
}
if (!disconnected && FD_ISSET(web_server_socket, &read_set))
{
disconnected = recv_and_send(web_server_socket, incomming_socket);
}
if (disconnected)
break;
}
close(web_server_socket);
close(incomming_socket);
}
}
int recv_and_send(from_socket, to_socket)
{
char buffer[1024];
for (;;)
{
len = recv_all(from_socket, buffer, sizeof(buffer));
if (len < 0)
return 1; /* Disconnect */
if (len == 0)
break; /* No more to read for now */
if (send_all(to_socket, buffer, len) < 0)
return 1; /* Disconnect */
}
return 0;
}
int recv_all(socket_fd, char *buffer, const size_t buflen)
{
size_t total_recv = 0;
size_t remaining_len = buflen;
while (remaining_len > 0)
{
ssize_t len = recv(socket_fd, buffer + total_recv, remaining_len);
if (len < 0)
{
if (errno == EWOULDBLOCK)
break; /* No more to read at the moment */
return -1; /* An error */
}
if (len == 0)
break; /* Connection closed */
total_recv += len;
remaining_len -= len;
}
return total_recv;
}
[The rest I leave as an exercise.]
The main difference with your code, is that the main loop is much simpler. You don't need multiple accept calls (why do you need it?) or several different read and write functions. Parts of my code can be even further simplified, like the recv_all function.
It should also be noted that my code above only handles one connection at a time. One way to solve this is to create a new thread for each incoming connection, or use a more advance method using lists of connections and buffers, and select to multiplex between them and the listening socket.