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.
Related
I am attempting to make a proxy server, currently want to know why the iPhone I am testing it with sends a CONNECT request, gets the response of "HTTP 200 Connection Established" and usually never responds after that.
(sometimes it will respond instantly with "0" or NULL)
I am not actually connecting to where the iPhone wants to go, but I am sending back a response that indicates the proxy has connected
Terminal Output:
./proxy 9000
At this point I enter my local ip in the iPhone proxy settings
Example output:
REC:
CONNECT clientmetrics.kik.com:443 HTTP/1.1
Host: clientmetrics.kik.com
User-Agent: Kik/14.4.0.11622 CFNetwork/897.15 Darwin/17.5.0
Connection: keep-alive
Proxy-Connection: keep-alive
Sent:
HTTP/1.1 200 Connection Established
REC:
// Typically \0 or a 0, or no recv takes place
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
if(argc == 2) {
int main(int argc, char* argv[]) {
system("clear");
// Set up socket, family, port, ip address
int serversocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serverinfo;
serverinfo.sin_family = AF_INET;
serverinfo.sin_addr.s_addr = INADDR_ANY;
serverinfo.sin_port = htons(atoi(argv[1]));
// bind server info to socket
if(bind(serversocket, (struct sockaddr*)&serverinfo, sizeof(serverinfo)) == -1) {
printf("failed to bind port to socket, change port\n");
return -1;
}
// accept a connection
listen(serversocket, 1);
int clientsocket = accept(serversocket, NULL, NULL);
// recv and print client message
char buffer[2048];
memset(buffer, 0, sizeof(buffer));
if(recv(clientsocket, buffer, sizeof(buffer), 0) == -1) {
printf("Failed in recv function\n");
} else {
printf("REC\n%s\n", buffer);
}
// send Connection Established
char* sendbuffer = "HTTP/1.1 200 Connection Established";
if(send(clientsocket, sendbuffer, sizeof(sendbuffer), 0) == -1) {
printf("Failed in send function\n");
} else {
printf("Sent:\n%s\n", sendbuffer);
// Recv response from iPhone
memset(buffer, 0, sizeof(buffer));
if(recv(clientsocket, buffer, sizeof(buffer), 0) == -1) {
printf("Failed in recv function\n");
} else {
printf("REC:\n%s\n", buffer);
}
}
} else {
printf("Usage: ./proxy <port>\n");
return 0;
}
}
Was just messing around some more and found that the iPhone will never respond beyond my CONNECT request because the connection must be closed after the proxy responds with HTTP 200 - then the connection can be reestablished and the iphone will continue to send data
i develop a program where i make i HTTPS requests in multithreading.
All work fine, however i need toimpleent use of proxy.
At the moment, i have this function for HTTPS Request :
struct string_builder* webrequest(const char* DEST_IP, const int DEST_PORT, const char* REQUEST) {
// Initialize ssl libraries and error messages
SSL_CTX *ssl_ctx = SSL_CTX_new (SSLv23_client_method());
// create a socket
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("Unable to create socket");
return NULL;
}
// destination info
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET; // host byte order
dest_addr.sin_port = htons(DEST_PORT); // short, network port
dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); // destination address
memset(&(dest_addr.sin_zero), '\0', 8); // zero out the rest of the struct
// connect to the server
int status = connect(sockfd, (struct sockaddr*) &dest_addr, sizeof(struct sockaddr_in));
if (status == -1) {
perror("Unable to connect to the server");
close(sockfd);
return NULL;
}
// create SSL connection and attach it to the socket
SSL *conn = SSL_new(ssl_ctx);
SSL_set_fd(conn, sockfd);
SSL_connect(conn);
// send an encrypted message
ssize_t sendsize = SSL_write(conn, REQUEST, strlen(REQUEST));
if (sendsize == -1) {
perror("Unable to send to the server");
{
char *buf = malloc(sizeof(char) * 256);;
u_long err;
while ((err = ERR_get_error()) != 0) {
ERR_error_string_n(err, buf, sizeof(buf));
printf("*** %s\n", buf);
}
free(buf);
}
SSL_shutdown(conn);
ERR_free_strings();
ERR_remove_state(0);
SSL_CTX_free(ssl_ctx);
close(sockfd);
return NULL;
}
size_t i = 1;
struct string_builder *result = NULL;
result = string_builder_init();
while (i) {
// receive the response
const int RESPONSE_SIZE = 512;
char *response = malloc(sizeof(char)*512);
ssize_t recsize = SSL_read(conn, response, RESPONSE_SIZE-1);
if (recsize == -1) {
perror("Unable to send to the server");
SSL_shutdown(conn);
ERR_free_strings();
ERR_remove_state(0);
SSL_CTX_free(ssl_ctx);
close(sockfd);
return NULL;
}
response[recsize] = '\0';
if (recsize <= 0)
{
free(response);
break;
}
else if (i > 2 && recsize > 6)
{
string_builder_pushs(result, response);
}
free(response);
++i;
}
// close ssl connection
SSL_shutdown(conn);
ERR_free_strings();
ERR_remove_state(0);
SSL_free(conn);
SSL_CTX_free(ssl_ctx);
close(sockfd);
return result;
}
I use socket/send/recv function for socket, openssl library for HTTPS requests.
All work fine, no leak without proxy, but when i try to use a "CONNECT command" to connect to google (and socket connexion to proxy host), i have an error when i want to send.
Thanks in advance.
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;
}
For some reason i am getting error an 57 - socket is not connected.
Why?
Console output:
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6,lt;q=0.4,nl;q=0.2,ru;q=0.2
Can't write to socket 57
The code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PORT 8080
#define PROTOCOL 0
#define BACKLOG 10
#define BUFLEN 1500
void str_server(int sock)
{
char buf[1025];
const char* filename = "index.html";
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("Can't open file for reading");
return;
}
while (!feof(file))
{
int rval = fread(buf, 1, sizeof(buf), file);
if (rval < 1)
{
printf("Can't read from file");
fclose(file);
return;
}
int off = 0;
do
{
int sent = send(sock, &buf[off], rval - off, 0);
if (sent < 1)
{
printf("Can't write to socket %d", errno);
fclose(file);
return;
}
off += sent;
}
while (off < rval);
}
fclose(file);
}
int main()
{
int fd;
int connfd;
// For bind()
struct sockaddr_in addr;
// For accept()
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
// For reading and writing
ssize_t i;
ssize_t rcount;
char buffer[BUFLEN];
// Open a socket
fd = socket(AF_INET, SOCK_STREAM, PROTOCOL);
if (fd == -1) {
printf("Error: unable to open a socket\n");
printf("Error code: %d\n", errno);
exit(1);
}
// Create an address
//memset(&addr, 0, sizeof addr);
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
int yes = 1;
if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 )
{
perror("setsockopt");
}
if ((bind(fd, (struct sockaddr *)&addr, sizeof(addr))) == -1) {
printf("Error: unable to bind\n");
printf("Error code: %d\n", errno);
exit(1);
}
// List for connections
if ((listen(fd, BACKLOG)) == -1) {
printf("Error: unable to listen for connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
// Accept connections
connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
// Read data
rcount = read(connfd, buffer, BUFLEN);
if (rcount == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
for (i = 0; i < rcount; i++) {
printf("%c", buffer[i]);
}
//write(connfd, buffer, rcount);
str_server(fd);
// Bye
//close(connfd);
return 0;
}
You're sending to the listening socket, when you should be sending to the accepted/connected one.
To fix this pass the connected socket:
str_server(connfd);
i have created a simple socket connection which sends a request to a node.js app and receives some random data and then sends back the data but it sends and receives the data correctly but does not send back the random data
char *httpbody;
struct addrinfo hints, *result;
const char *host = "localhost";
char user[512] = "test#gmail.com";
char pass[512] = "test";
char headers[512];
srand(time(NULL));
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(host, "3000", &hints, &result) != 0) {
freeaddrinfo(result);
perror("Could not resolve hostname.");
exit(1);
}
int newsocket = socket(result->ai_family, result->ai_socktype, 0);
if (newsocket == -1) {
perror("Could not create socket.");
freeaddrinfo(result);
close(newsocket);
exit(1);
}
if (connect(newsocket, result->ai_addr, result->ai_addrlen) == -1) {
perror("Could not connect.");
freeaddrinfo(result);
close(newsocket);
exit(1);
}
sprintf(headers, "GET /auth?user=%s&pass=%s HTTP/1.1\r\n"
"User-Agent: Device\r\n"
"Accept-Language: de,en;q=0.7,en-us;q=0.3\r\n"
"Content-Type: text/html; charset=UTF-8\r\n"
"Connection: Close\r\n\r\n", user, pass);
if ((send(newsocket, headers, strlen(headers), 0)) == -1) {
perror("Could not send data.");
freeaddrinfo(result);
close(newsocket);
exit(1);
}
char response[51201] = "";
recv(newsocket, response, 51200, 0);
response[strlen(response)] = '\0';
httpbody = strstr(response, "\r\n\r\n");
if (httpbody) {
httpbody += 8;
}
int data = rand() % 255 + 1;
sprintf(headers, "GET /add_data?user=%s&data=%i&"
"uid=%s HTTP/1.1\r\n"
"User-Agent: Device\r\n"
"Accept-Language: de,en;q=0.7,en-us;q=0.3\r\n"
"Content-Type: text/html; charset=UTF-8\r\n"
"Connection: Close\r\n\r\n", user, data, httpbody);
if ((send(newsocket, headers, strlen(headers), 0)) == -1) {
perror("Could not send data.");
freeaddrinfo(result);
close(newsocket);
exit(1);
}
printf("done");
freeaddrinfo(result);
close(newsocket);
when i remove the revc request it works fine and it does not show any errors and i am completely lost
Check this lines of code:
recv(newsocket, response, 51200, 0);
response[strlen(response)] = '\0';`
recv doesn't return null-terminated data, so you cannot use strlen for determine size of data.
You must use return value of recv instead:
int data_size = recv(newsocket, response, 51200, 0);
An HTTP connection ends each time when you specify "Connection: close" in HTTP 1.1, thus the socket is not valid after you finish reading the response from the server.
Possible solutions are:
Remove "Connection: close" header from the first request
Connect() to the server again after you recv() the response