I am able to access resource from tomcat server using below URL from my browser,
http://localhost:8080/test/file1.xml
Request header:
Status Code:200 OK
Request Headersview parsed
GET /test/file1.xml HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Response Headersview parsed
Response header:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"9-1399430961358"
Last-Modified: Wed, 07 May 2014 02:49:21 GMT
Content-Type: application/xml
Content-Length: 9
Date: Fri, 16 May 2014 16:37:10 GMT
but am unable to access the same resource using below windows client program, Can you please let me know the reason?
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 65536
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "GET /test/file1.xml HTTP/1.1";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("127.0.0.1", "8080", &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen-1, 0);
if ( iResult > 0 ){
recvbuf[iResult]='\0';
printf("Bytes received: %d, httpresponse: %s\n", iResult,recvbuf);
}
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
output is:
c:\code>client.exe
Bytes Sent: 28
Connection closed
This should work.
To send HTTP/1.0 request,
char *sendbuf = "GET /test/file1.xml HTTP/1.0\r\n\r\n ";
To send http 1.1 request,
char *sendbuf = "GET /test/file1.xml HTTP/1.1\r\nHost: localhost\r\n\r\n ";
The concept of virtual hosts allows more than one Web site on one system or Web server. HTTP/1.1 server supports so-called virtual hosts. Hence, in an HTTP/1.1 GET request, it is mandatory to include a request header called "Host", to select one of the virtual hosts.
Related
I would like to download a PDF file with a socket. I receive a "400 Bad Request" error from the server, saying "The plain HTTP request was sent to HTTPS port", like shown in the image below (I open it as an HTML page):
I change the port from 443 to 80, but I don't get a response from the server. I have nothing in file.pdf when I change the port to 80.
This is my console output:
Connected to server via socket 268
Bytes Sent: 109
Bytes received: 0
Received byte = 100
Total data = 100Bytes received: 0
Received byte = 100
Total data = 200Bytes received: 0
Received byte = 100
Total data = 300Bytes received: 0
Received byte = 100
Total data = 400Bytes received: 0
Received byte = 30
Total data = 430Connection closed
Received byte = 0
Total data = 430Reply received
This is my code. I open the socket and I connect to the server, but I'm not receiving the file:
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return 1;
}
sockaddr_in Serv_Addr;
//intialisation
struct addrinfo* result = NULL;
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
//socket configuration
SOCKET TcpClientSocket = -1;
int ret = 0;
TcpClientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (TcpClientSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
Serv_Addr.sin_family = AF_INET;
Serv_Addr.sin_port = htons(443);
Serv_Addr.sin_addr.s_addr = inet_pton(AF_INET, "47.88.2.145", &Serv_Addr.sin_addr); //connect to www.axmag.com, link pdf file http://www.axmag.com/download/pdfurl-guide.pdf
printf("Connected to server via socket %u\n", TcpClientSocket);
//connection
iResult = -1;
iResult = connect(TcpClientSocket, (sockaddr*)& Serv_Addr, sizeof(Serv_Addr));
printf("%d", iResult);
if (iResult == SOCKET_ERROR) {
wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
iResult = closesocket(TcpClientSocket);
if (iResult == SOCKET_ERROR)
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// send request
const char* message;
message = "GET /download/pdfurl-guide.pdf HTTP/1.1\r\nHost: www.axmag.com\r\n\r\n Connection: keep-alive\r\n\r\n Keep-Alive: 300\r\n";
// test send succeded
iResult = send(TcpClientSocket, message, strlen(message), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(TcpClientSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection for sending since no more data will be sent
// the client can still use the ConnectSocket for receiving data
iResult = shutdown(TcpClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(TcpClientSocket);
WSACleanup();
return 1;
}
FILE* stream;
fopen_s(&stream, "1.html", "w+");
/////receive response from server
int totalData = 0, received_data = 0;
do
{
char server_reply[100];
received_data = recv(TcpClientSocket, server_reply, sizeof server_reply, 0);
if (received_data > 0)
printf("Bytes received: %d\n", iResult);
else if (received_data == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
totalData += received_data;
fwrite(server_reply, received_data, 1, stream);
printf("\nReceived byte = %d\nTotal data = %d", received_data, totalData);
} while (received_data > 0);
printf("Reply received\n");
if (stream)
{
if (fclose(stream))
{
printf("The file 'crt_fopen.c' was not closed\n");
}
}
You need a TLS library so you can speek https to the server.
This is far too big to post an answer in C but since you are using Winsock you might as well use the builtin schannel.
I'm learning winsock programming. I have a question about the code provided in msdn: https://learn.microsoft.com/en-us/windows/desktop/winsock/complete-client-code
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
Why the client have to use a loop with socket() and connect(), the Linux version of the program doesn't need it. Can I remove it? or is it implementation-dependency ?
Such a loop is common when using getaddrinfo (even on Linux).
The getaddrinfo function can return a list with multiple possible remote addresses, or multiple address families, or multiple protocols. The loop tries all of the addresses in the list until it successfully connects.
I am try to write simple HTTP client with c ,
when i execute my program some time I gets data from website some time not.
to be specific recv() blocks, and the connection shutdown.
what the best way to deal with this problem ? I still want to get the website data.
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
if (iResult = getaddrinfo(s1, "http", &hints, &result)) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen-1, 0);
if ( iResult > 0 ) {
flag = 1;
recvbuf[iResult] = '\0';
printf("%s\n",recvbuf);
}
else if ( iResult == 0 ) {
if(!flag) {
printf("conection close before recv data\n");
} else {
printf("conection close\n");
break;
}
}
else {
printf("recv failed with error: %d\n", WSAGetLastError());
}
} while(iResult>1);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
i've used HTTP protocol concept and sent to each url i've tried in this templet: sendbuf ="GET /[url path] HTTP 1.0/r/nHost:[www.pure_url.com]/r/n/r/n"
edit: I've tried [DaSourcerer advise] , changed to HTTP/1.1 and added Connection: close , still some time i get the data some times not.
also I added:
int tcp_timeout=10000;
unsigned int sz = sizeof(tcp_timeout);
setsockopt(ConnectSocket, SOL_SOCKET, SO_RCVTIMEO,
(char*)&tcp_timeout, sz);
this idea didn't help.
I think your timeouts are too strict. Your sent headers will also provoke servers to wait for further input. Try this:
GET /path HTTP/1.1
Host: example.com
Connection: close
It also bears mentioning that Host is a header introduced in HTTP/1.1. It has no meaning in HTTP/1.0. You may also be interested into RFC 7230, section 3.3.3 as you are almost certainly going to encounter chunk-encoded messages in HTTP/1.1. Don't worry, though: it can be parsed with a simple state machine.
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.
Below is the code, I took from MSDN's tutorial examples for Winsock server programming. The code seems to be working fine. When I type http://localhost:27015 in my browser, the code responds appropriately. However, I am unable to work with the string sent by the browser as request and stored here as character array in recvbuf. For example, I am not able to printf the buffer or use fwrite either. The program terminates immediately. Please help.
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main(void)
{
WSADATA wsaData;
SOCKET ListenSocket = INVALID_SOCKET,
ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
hints;
char recvbuf[DEFAULT_BUFLEN];
char *sendbuf = "HTTP/1.1 200 OK \r\n Date: Fri, 31 Dec 1999 23:59:59 GMT \r\n Content- Type: text/html\r\n";
int iResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
else
printf("\nInitialising winsock...done");
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
else
printf("\nResolving server address...done");
//localhost:27015/
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
else
printf("\nCreating connection socket...done");
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
printf("\nCreating listening socket...done");
printf("\nWaiting for connection... ");
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// No longer need server socket
closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do
{
iResult = recv(ClientSocket, recvbuf, recvbuflen,0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(ClientSocket,sendbuf,(int)strlen(sendbuf), 0 );
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}while(iResult>0);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
//Appended later
printf("\n");
int i =0;
while(i<120)
{
printf("%c",recvbuf[i]);
++i;
}
return 0;
}
Thanks!
iResult = recv(ClientSocket, recvbuf, recvbuflen,0);
In the above, the data received through recv() is not zero-terminated. iResult is the length of the data, to output it as text:
printf("%.*s", iResult, recvbuf);
Adding the following function helped. The hint was already provided by Maxim when he said
data received through recv() is not
zero-terminated.
void handleBuffer()
{
recvbuf[DEFAULT_BUFLEN-1]='\0';
printf("*********************\n");
printf("%s",recvbuf);
}
I also increased my DEFAULT_BUFLEN to 4096. Call the function to print the output anytime.