Socket programming in C using http post - c

Want to do client-server programming using c in windows7, it should send string to server using http POST method. The paramater in POST method should include the ip-address etc:
I got this code from http://souptonuts.sourceforge.net/code/http_post.c.html and changed it for running it on windows, but still 1 error is coming:
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <netdb.h>
#include <assert.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#define SA struct sockaddr
#define MAXLINE 4096
#define MAXSUB 200
#define LISTENQ 1024
extern int h_errno;
ssize_t process_http(int sockfd, char *host, char *page, char *poststr)
{
char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
ssize_t n;
snprintf(sendline, MAXSUB,
"POST %s HTTP/1.0\r\n"
"Host: %s\r\n"
"Content-type: application/x-www-form-urlencoded\r\n"
"Content-length: %d\r\n\r\n"
"%s", page, host, strlen(poststr), poststr);
write(sockfd, sendline, strlen(sendline));
while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = '\0';
printf("%s", recvline);
}
return n;
}
int main(void)
{
int sockfd;
struct sockaddr_in servaddr;
char **pptr;
//********** You can change. Puy any values here *******
char *hname = "souptonuts.sourceforge.net";
char *page = "/chirico/test.php";
char *poststr = "mode=login&user=test&password=test\r\n";
//*******************************************************
char str[50];
struct hostent *hptr;
if ((hptr = gethostbyname(hname)) == NULL) {
fprintf(stderr, " gethostbyname error for host: %s: %s",
hname, hstrerror(h_errno));
exit(1);
}
printf("hostname: %s\n", hptr->h_name);
if (hptr->h_addrtype == AF_INET
&& (pptr = hptr->h_addr_list) != NULL) {
printf("address: %s\n",
inet_ntop(hptr->h_addrtype, *pptr, str,
sizeof(str)));
} else {
fprintf(stderr, "Error call inet_ntop \n");
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// bzero(&servaddr, sizeof(servaddr));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, str, &servaddr.sin_addr);
connect(sockfd, (SA *) & servaddr, sizeof(servaddr));
process_http(sockfd, hname, page, poststr);
close(sockfd);
exit(0);
}
The error which is coming on MinGW compiler is:
httppost.c:33:12: error: conflicting types for 'WSAGetLastError'
In file included from httppost.c:5:0:
c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/winsock2.h:594:32: n
e: previous declaration of 'WSAGetLastError' was here

The code you've got is under linux based systems, but in MinGW (Windows) unfortunately the identifier h_errno is taken before.
The problem is this line
extern int h_errno;
it's defined previously in windows header files, then you can not use it:
#define h_errno WSAGetLastError()
Just use another identifier instead of h_errno, or even just remove that line!

Maybe you should try the wininet library.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa383630(v=vs.85).aspx

Related

503 - Service temporarily unavailable

I need simple HTTP client on Raspberry PI zero with Raspbian. I used few example codes, but when i send about 7 requests then i can download just page with this error:
503 Service temporarily unavailable
There is no available fastcgi process to fullfill your request.
One of used codes:
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netdb.h>
#include <unistd.h>
#define SA struct sockaddr
#define MAXLINE 4096
#define MAXSUB 200
ssize_t process_http(int sockfd, char *host, char *page)
{
ssize_t n;
snprintf(sendline, MAXSUB,
"GET %s\r\n"
"Host: %s\r\n"
"Connection: close\n"
"\n", page, host);
write(sockfd, sendline, strlen(sendline));
while ((n = read(sockfd, recvline, MAXLINE)) > 0)
{
recvline[n] = '\0';
}
printf("%s", recvline);
return n;
}
and in main is this:
int sockfd;
struct sockaddr_in servaddr;
char **pptr;
char *hname = "plankter.cz";
char *page = "http://plankter.cz/iot/list.json";
char str[50];
struct hostent *hptr;
if ((hptr = gethostbyname(hname)) == NULL) {
fprintf(stderr, " gethostbyname error for host: %s: %s",
hname, hstrerror(h_errno));
exit(1);
}
printf("hostname: %s\n", hptr->h_name);
if (hptr->h_addrtype == AF_INET
&& (pptr = hptr->h_addr_list) != NULL) {
printf("address: %s\n",
inet_ntop(hptr->h_addrtype, *pptr, str,
sizeof(str)));
} else {
fprintf(stderr, "Error call inet_ntop \n");
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, str, &servaddr.sin_addr);
connect(sockfd, (SA *) & servaddr, sizeof(servaddr));
process_http(sockfd, hname, page);
close(sockfd);
In this example i download json, but when i read php or txt, i have same problem. I tried some another example codes using sockets, example with happyhttp library and all give me same result after 7 requests. I think it doesn't close connection. I need to send http request and recieve data, and i need to do it few times in minute.
Thanks for all ideas.
You provide a full URI to the GET field:
char *page = "http://plankter.cz/iot/list.json";
...
snprintf(sendline, MAXSUB,
"GET %s\r\n"
"Host: %s\r\n"
"Connection: close\n"
"\n", page, host);
You should not include protocol and host name.
Try this instead:
char *page = "/iot/list.json";

Sockets, client server communication using SOCK_DGRAM, epoll

I'm trying to write a program with AF_INET, SOCK_DGRAM, where client connects to server sends it message "First message" and then the server responds to client with "Second message".
Q1: In my code server receives "First message", however client doesn't get server response "Second message", why?
Q2: In client I connect to server using msg_addr.sin_addr.s_addr =INADDR_ANY; I would like to change it for something like: msg_addr.sin_addr.s_addr =htonl(inet_addr("172.126.154.12")); where ip "172.126.154.12"is server ip;
server.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
typedef struct{
int type;
int arg1;
int arg2;
int result;
char name[50];
}Msg;
#define WRITE(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));}
#define FAILURE_EXIT(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));exit(-1);}
int web_fd, epoll;
struct sockaddr_in server_addr;
Msg msg;
struct sockaddr msg_addr;
int main(int argc, char *argv[]){
if((web_fd = socket(AF_INET, SOCK_DGRAM,0)) == -1) FAILURE_EXIT("Failed to create communication endpoint web_fd\n");
int yes=1;
if (setsockopt(web_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) == -1) FAILURE_EXIT("setsockopt web_fd\n");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9992);
server_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(web_fd,(const struct sockaddr*) &server_addr,sizeof(struct sockaddr)) == -1) FAILURE_EXIT("Failed to assign server_addr to a web_fd: %s\n",strerror(errno));
epoll = epoll_create1(0);
if(epoll == -1) FAILURE_EXIT("Failed to create new epoll instance: %s\n",strerror(errno));
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = web_fd;
if(epoll_ctl(epoll,EPOLL_CTL_ADD,web_fd,&event)== -1) FAILURE_EXIT("Failed to register web_fd file descriptor on epoll instance: %s\n",strerror(errno));
printf("Server starts loop.\n");
while(1){
struct epoll_event event;
WRITE("Waiting for client message...\n");
int nfd = epoll_wait(epoll,&event,1,-1);
if(event.data.fd == web_fd){
recvfrom(event.data.fd,&msg,sizeof(Msg),0 ,&msg_addr,0);
WRITE("Received message from client %s\n",msg.name);
strcpy(msg.name,"Second message");
sendto(event.data.fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr, (socklen_t) sizeof(msg_addr) );
}else{
WRITE("Unknown descriptor\n");
}
}
}
client.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
typedef struct{
int type;
int arg1;
int arg2;
int result;
char name[50];
}Msg;
#define WRITE(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));}
#define FAILURE_EXIT(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));exit(-1);}
int socket_fd;
struct sockaddr_in msg_addr;
Msg msg;
int main(int argc, char *argv[]){
struct sockaddr_in msg_addr;
msg_addr.sin_family = AF_INET;
msg_addr.sin_addr.s_addr =INADDR_ANY;
msg_addr.sin_port = htons(9992);
socket_fd = socket(AF_INET, SOCK_DGRAM,0);
if(socket_fd == -1) FAILURE_EXIT("Failed to create client socket\n");
if(connect(socket_fd, (const struct sockaddr*) &msg_addr, sizeof(struct sockaddr)) == -1) FAILURE_EXIT("Failed to assign server_addr to a web_fd: %s\n",strerror(errno));
strcpy(msg.name,"First message ");
sendto(socket_fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr,(socklen_t) sizeof(Msg));
WRITE("Waiting..\n");
recvfrom(socket_fd,&msg,sizeof(Msg),0 ,0,0);
WRITE("f %s\n",msg.name);
WRITE("I registered\n");
sleep(400);
}
In server code change recvfrom() call as this
socklen_t addrsize;
recvfrom(event.data.fd,&msg,sizeof(Msg),0 ,&msg_addr, &addrsize);
and change subsequent sendto() call as this
sendto(event.data.fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr, addrsize);

C - Mavlink program : sendto fails and returns EINVAL while connecting to a drone

I'm trying to use a mavlink sample developed by Parrot to control a Bebop2 using mavlink protocol (link here).
In order to send a message to the drone, they use the sendto function but I encounter an issue I cannot resolve : everytime I try to make the program works, I recieve an error and after a bit of investigation, I found that it's the 'sendto' used in this code (in the mavlink_comm_send_msg function) that returns an EINVAL error type (code located inside the mavlink_comm.c file in the src directory) :
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <poll.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <mavlink.h>
#include "mavlink_comm.h"
#define MAVLINK_COMM_BUFSIZE 4096
struct mavlink_comm {
int sock;
struct sockaddr_in remote_addr;
unsigned char tx_buffer[MAVLINK_COMM_BUFSIZE];
unsigned int tx_bufidx;
unsigned char rx_buffer[MAVLINK_COMM_BUFSIZE];
unsigned int rx_bufidx;
void (*cb)(mavlink_message_t *msg, void *user_data);
void *user_data;
};
struct mavlink_comm *mavlink_comm_new(struct mavlink_comm_cfg *cfg)
{
struct sockaddr_in locAddr;
struct mavlink_comm *c;
struct hostent *server;
if (!cfg)
return NULL;
c = calloc(1, sizeof(*c));
if (!c)
return NULL;
c->cb = cfg->cb;
c->user_data = cfg->user_data;
c->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset(&locAddr, 0, sizeof(locAddr));
locAddr.sin_family = AF_INET;
locAddr.sin_addr.s_addr = INADDR_ANY;
locAddr.sin_port = htons(cfg->local_port);
if (cfg->remote_addr && cfg->remote_addr[0] != '\0') {
server = gethostbyname(cfg->remote_addr);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host %s\n",
cfg->remote_addr);
exit(0);
}
bzero((char *) &c->remote_addr, sizeof(c->remote_addr));
c->remote_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&c->remote_addr.sin_addr.s_addr,
server->h_length);
c->remote_addr.sin_port = htons(cfg->remote_port);
}
/* Bind the socket to port 14551
* necessary to receive packets from qgroundcontrol */
if (-1 == bind(c->sock,(struct sockaddr *)&locAddr,
sizeof(struct sockaddr))) {
perror("error bind failed");
goto exit_close;
}
return c;
exit_close:
close(c->sock);
free(c);
return NULL;
}
static inline int mavlink_comm_send_data_internal(struct mavlink_comm *c)
{
int size = sizeof(struct sockaddr_in);
return sendto(c->sock, c->tx_buffer, c->tx_bufidx, 0,
(struct sockaddr*)&c->remote_addr,
sizeof(struct sockaddr_in));
}
int mavlink_comm_send_msg(struct mavlink_comm *c, mavlink_message_t *msg)
{
if (!c || !msg)
return -EINVAL;
int len = mavlink_msg_to_send_buffer(c->tx_buffer, msg);
return sendto(c->sock, c->tx_buffer, len, 0,
(struct sockaddr*)&c->remote_addr,
sizeof(struct sockaddr_in));
}
I looked at other related posts and tried several things to make it work but none of them were successful. The cast seems correct and I verified dest_len argument, so I'm quite lost.
Thanks a lot for your help.

TCP client fetches HTML in C socket

I'm trying to write a TCP client that fetches HTML. The program would accept a website from user and print out the content. Right now my code only fetches a HTML back saying error 408 request timeout error page.
Where is the problem?
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char* argv[])
{
char *domain = argv[1];
char *path = strchr(domain, '/');
*path++ = '\0';
//printf("host: %s; path: %s\n", domain, path);
int sock, bytes_recieved;
char send_data[1024],recv_data[9999];
struct sockaddr_in server_addr;
struct hostent *he;
he = gethostbyname(domain);
if (he == NULL){
herror("gethostbyname");
exit(1);
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0))== -1){
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
server_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1){
perror("Connect");
exit(1);
}
snprintf(send_data, sizeof(send_data), "GET /%s HTTP/1.1\r\n Host: %s\r\n \r\n \r\n", path, domain);
//printf("%s\n", send_data);
send(sock, send_data, strlen(send_data), 0);
printf("Data sended.\n");
bytes_recieved = recv(sock, recv_data, 9999, 0);
recv_data[bytes_recieved] = '\0';
close(sock);
printf("Data reveieved.\n");
printf("%s\n", recv_data);
return 0;
}
For example, right now if I'm trying to run ./client www.facebook.com It would return a HTML page says error occurs
Check your HTTP Get request, it should be
GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n

access data from server udp

I have a problem, I have a client server udp, in server side I need to access data from client side to control movement of the robot. For the experiment I use to print "oke" if the value of the data is 1.
here the code program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MYPORT 4950
#define MAXBUFLEN 100
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
char dt[30];
char buf[MAXBUFLEN];
int main()
{
printf("‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐\n");
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("socket");
exit(1); }
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero),'\0',8);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1){
perror("bind");
exit(1); }
while(1){
addr_len = sizeof(struct sockaddr);
if((numbytes=recvfrom(sockfd,buf,MAXBUFLEN-1,0,(struct sockaddr *)&their_addr,&addr_len))==-1)
{
perror("recvfrom");
exit(1);}
buf[numbytes]='\0';
printf("%s : \"%s\"\n", inet_ntoa(their_addr.sin_addr), buf);
if (buf[0]==1)
{ printf("oke\n");}
printf("Me : ");
scanf("%s", dt);
if((numbytes=sendto(sockfd,dt,strlen(dt),0,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)))==-1)
{
perror("sendto");
exit(1);
}
}
close(sockfd);
return 0;
}
when I put "1" in client side the result is:
‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐
130.130.66.76 : "1"
Me :
even in the program there are:
if (buf[0]==1)
{ printf("oke\n");}
why the program cannot access to inside of if?
Try if (buf[0]=='1')
Number characters map to different ASCII values than their number, so, for example, '1'==49.

Resources