I have a C client and a Java server (Tomcat via eclipse).
1- The C client is meant to perform an HTTP Post of a string to the Java Server [Gives error].
2- The server has a localhost HTML form-page that is meant to save any string it receives which is posted and writes it to file [Works fine; Tested]
The problem I am having is that I am unable to get the server to successfully receive and save the string post from the client. The server responds with "error 400 bad request" instead.
However, I am able to get the server to save any string that is manually entered via the html form page.
I just need to get the client instead of me, to post to the html form page (unless there is a better way for the client to post to the server without the need of a form page).
I am no expert in network and socket programming. Any help is greatly appreciated.
Here is the Java Server Code:
// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
// Extend HttpServlet class
public class HelloForm extends HttpServlet {
private OutputStream ostream;
// Method to handle GET method request.
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// Set response content type
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Using GET Method to Read Form Data";
String docType =
"<!doctype html public \"-//w3c//dtd html 4.0 " +
"transitional//en\">\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body bgcolor=\"#f0f0f0\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" +
"<ul>\n" +
" <li><b>First Parameter</b>: " //Displayed on result page NOT html page
+ request.getParameter("first_name") + "\n" +
" <li><b>Last Parameter</b>: " //Displayed on result page NOT html page
+ request.getParameter("last_name") + "\n" +
"</ul>\n" +
"</body></html>");
//printing result to console:
System.out.println(request.getParameter("first_name"));
System.out.printf("Parameter Entered: %s\n", request.getParameter("first_name"));
////printing results to file:
{
try(PrintWriter serveroutput = new PrintWriter(new BufferedWriter(new FileWriter("/home/salimramjean/Desktop/ServerOutput.txt",true)))) {
serveroutput.println(request.getParameter("first_name"));
}
}
}
// Method to handle POST method request.
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
HTML form page of server:
<html>
<body>
<form action="HelloForm" method="POST">
Parameter: <input type="text" name="first_name">
<br />
<input type="submit" value="Submit" />
</form>
</body>
</html>
<?
Here is the C Client code:
#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include <netdb.h> /* struct hostent, gethostbyname */
#include <unistd.h>
void error(const char *msg) { perror(msg); exit(0); }
int main(int argc,char *argv[])
{
/* first what are we going to send and where are we going to send it? */
int portno = 8080;
char *host = "192.168.1.65"; /* localhost: 127.0.0.1 or 192.168.1.65 */
char *message_fmt = "POST /Parameter=%s&command=%s HTTP/1.1\n\n";
struct hostent *server;
struct sockaddr_in serv_addr;
int sockfd, bytes, sent, received, total;
char message[1024],response[4096];
if (argc < 3) { puts("Parameters: <apikey> <command>"); exit(0); }
/* fill in the parameters */
sprintf(message,message_fmt,argv[1],argv[2]);
printf("Request:\n%s\n",message);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
/* lookup the ip address */
server = gethostbyname(host);
printf("ip address: %s\n\n", host);
if (server == NULL) error("ERROR, no such host");
/* fill in the structure */
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
/* connect the socket */
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
/* send the request */
printf("Sending request\n\n");
total = strlen(message);
sent = 0;
do {
//bytes = write(sockfd,a+sent,total-sent);
bytes = write(sockfd,message+sent,total-sent);
if (bytes < 0)
error("ERROR writing message to socket");
if (bytes == 0)
break;
sent+=bytes;
} while (sent < total); //while (sent < 0);
printf("Post request sent \n");
//receive the response
printf("Receiving response \n");
memset(response,0,sizeof(response));
total = sizeof(response)-1;
received = 0;
do {
bytes = read(sockfd,response-received,total-received);
if (bytes < 0)
error("ERROR reading response from socket");
if (bytes == 0)
break;
received+=bytes;
} while(received < total); //while (received < 0);
printf("Response received\n");
if (received == total)
error("ERROR storing complete response from socket");
/* close the socket */
close(sockfd);
/* process response */
printf("\nServer Response:\n%s\n\n",response);
return 0;
}
Here is the web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>FormServ</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>HelloForm</servlet-name>
<servlet-class>HelloForm</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloForm</servlet-name>
<url-pattern>/HelloForm</url-pattern>
</servlet-mapping>
</web-app>
Example of how I run and compile it:
$ ./client IamSendingThisString submit
Result displayed in Terminal:
Request:
POST /Parameter=IamSendingThisString&command=submit HTTP/1.1
ip address: 192.168.1.65
Sending request
Post request sent
Receiving response
Response received
Server Response:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Tue, 24 Feb 2015 09:22:15 GMT
Connection: close
0
Correct Changes made:
1- Edited POST header:
char *message_fmt = "POST /FormServ/HelloForm HTTP/1.1\r\nHost: %s:%d\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\nfirst_name=%s&last_name=%s\r\n";
2- Added content type:
char *contentType = "application/x-www-form-urlencoded";
3- Added Content length
Your problem in this line: "POST /Parameter=%s&command=%s HTTP/1.1\n\n"
I don't know what exactly parameters should be send, but it contains at least 2 errors:
1) Doesn't have symbol ? before prameters list. Should be /?Parameter=%s&command=%s if your servlet deployed in /, not some other page like /index.jsp
2) Doesn't ends with \r\n (ends with \n\n instead)
Also maybe you should send headers Content-length, Content-type and additional \r\n in the end or request.
Try to find some working socket client example and copy code. For example http://examples.javacodegeeks.com/core-java/net/socket/send-http-post-request-with-socket/