I have an assignment that requires me to build a very basic mail client to send an email on my school's server. If I open a command prompt on my computer and run telnet with these exact commands, the message goes through, but something in the program is causing it to kick back an error message. The exact response is:
451 4.5.0 SMTP protocol violation, see RFC 2821 e127si46647995qkb.26 - gsmtp
Here is the part of my code where I believe the issue to lie:
private void sendMessage(String from, String to, String subject, String msg) {
Socket socket = null;
DataOutputStream os = null;
DataInputStream is = null;
try {
socket = new Socket("ALT3.ASPMX.L.GOOGLE.COM", 25);
os = new DataOutputStream(socket.getOutputStream());
is = new DataInputStream(socket.getInputStream());
} catch (Exception e) {
System.out.println(e);
}
if (socket != null && os != null && is != null) {
try {
os.writeBytes("HELO\n");
os.writeBytes("MAIL From: <" + from + ">\n");
os.writeBytes("RCPT TO: <" + to + ">\n");
os.writeBytes("DATA\n");
os.writeBytes("From: <" + from + ">\n");
os.writeBytes(subject);
os.writeBytes(msg); // message body
os.writeBytes("\n.\n");
os.writeBytes("QUIT");
String responseLine;
while ((responseLine = is.readLine()) != null) {
System.out.println("Server: " + responseLine);
if (responseLine.indexOf("Ok") != -1) {
break;
}
}
Related
I have a larger block of Java code, but the important lines are these:
public static String tcp(String hostName, Number port, Number connectionTimeOutMs, Number readTimeOutMs, String message) {
String errmsg = "";
try (
Socket socket = new Socket();
) {
Inet4Address address = (Inet4Address) Inet4Address.getByName(hostName);
System.out.println("IP address:" + address.getHostAddress());
socket.connect(new InetSocketAddress(address, port.intValue()), connectionTimeOutMs.intValue());
socket.setSoTimeout(readTimeOutMs.intValue());
When I supply an IP address in the form "45.79.112.203" or "tcpbin.com", the code gives a SocketTimeoutException.
In the latter case, the line
System.out.println("IP address:" + address.getHostAddress());
gives the correct IP address, so the hostname is resolved correctly; it matches what ping tcpbin.com returns.
I want to be able to call the function with either an IPv4 address (in String format) or a hostname.
What am I doing wrong? Why does the socket fail to establish a connection, even with a high timeout of 60,000 ms?
Notes:
tcpbin.com is an "echo" server to test socket connections. It is only used as an example and should not be the cause of the problem.
Try the following:
echo "Text to send to TCP" | nc tcpbin.com 4242
You should get back the string that was just sent.
In the tcp() function, I pass in numbers in the form of a Number object, since the Java code gets called from Karate test framework via Java inter-op and JavaScript. JavaScript has the type Number, but no int or double.
===
Update:
Here a simple tcp server TcpServer.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) {
System.out.println("Listening on port 4242");
ServerSocket listener = null;
try {
do {
listener = new ServerSocket(4242);
Socket other = listener.accept();
System.out.println(">>> got a new connection from "
+ other.getInetAddress().toString() + " <<<");
other.getOutputStream().write("Blah blah".getBytes());
other.close();
listener.close();
} while (true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
===
Here a test class to test the tcp() function. It is the connect() statement that times out in case host != localhost.
TestTcpFunction.java:
import java.io.*;
import java.net.*;
public class TestTcpFunction {
public static void main(String[] args) {
String sendMessage = "Blah blah";
String host = (args.length==0)
? "localhost"
: "tcpbin.com";
String result = tcp(host, 4242, 30000, 30000, sendMessage);
System.out.println("result = " + result);
System.out.println("matches = " + result.equals(sendMessage));
}
public static String tcp(String hostName, Number port, Number connectionTimeOutMs, Number readTimeOutMs, String message) {
String errmsg = "";
try (
Socket socket = new Socket();
) {
Inet4Address address = (Inet4Address) Inet4Address.getByName(hostName);
System.out.println("trying to connect to:" + address.getHostAddress());
socket.connect(new InetSocketAddress(address, port.intValue()), connectionTimeOutMs.intValue()); // <<< times out if not localhost
socket.setSoTimeout(readTimeOutMs.intValue());
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // autoflush
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
out.print(message);
StringBuilder sb = new StringBuilder();
String line;
boolean addNewline = false;
while ((line = in.readLine()) != null) {
if (addNewline)
sb.append('\n');
sb.append(line);
if (line.lastIndexOf("</response>") >= 0)
break;
addNewline = true;
}
return sb.toString(); // The xml may not be well formed, for instance missing </response>
} finally {}
} catch (UnknownHostException e) {
errmsg = "Unknown host " + hostName;
} catch (SocketTimeoutException e) {
errmsg = "Socket connection timeout (before connection got established)";
} catch (SocketException e) {
errmsg = "Socket error: " + e.getMessage();
} catch (IOException e) {
errmsg = "Couldn't get I/O for the connection to " + hostName;
} catch (Exception e) {
errmsg = "Unknown socket error " + e.getMessage();
}
System.err.println(errmsg);
return "<Error> function tcp (Utils.java): " + errmsg + "</Error>";
}
}
===
Compile both with javac. Then start the server with java TcpServer.
Next run java TestTcpFunction in a different shell, without parameters.
The first time (with local host) it should work correctly.
Then run again, but with any parameter(s), like java TestTcpFunction 1
This time I get a timeout while trying to connect.
The code has been build and tested on my machine.
The client does not time out in connect. A simple output after connect shows that the connection is actually successfully:
socket.connect(new InetSocketAddress(address, port.intValue()), connectionTimeOutMs.intValue()); // <<< times out if not localhost
System.out.println("connected successfully");
Instead the program hangs while reading from the server. With the current code it will wait until the server closes the connection or has send a line with </response>. But the server tcpbin.com:4242 will not do anything like this. It will simply read anything and echo it back. To get a </response> string one actually has to send this string - which is not done.
Because of this the read will time out after a while based on the timeout set with socket.setSoTimeout. The resulting SocketTimeoutException is wrongly interpreted as connection timeout, but it is a read timeout.
Given that the code expects the echoed message to include the string </response> one must add it to the sent message:
String sendMessage = "Blah blah</response>";
This is still not enough though and a tcpdump shows that the message does not even get sent. This is because the expectation, that out.print(message); is affected by the autoflush is simply wrong - see I created a PrintWriter with autoflush on; why isn't it autoflushing?. Thus, one must explicitly flush the writer:
out.print(message);
out.flush();
tcpdump shows that the message is now actually send, but nothing is echoed back. This is because the echo server actually expects to read lines, but no line end was send yet. Adding it actually helps to send the message, get an echoed message back and break out of the loop:
String sendMessage = "Blah blah</response>\n";
And why did it work with localhost? Because the sample server did not actually behave like the echo server at tcpbin.com. It did not read anything but just sent a fixed message back and closed the connection.
I have connection to TCP server (ip,port) to which meter is connected. I'd like to read the specified data from this port because when I'm using standard read method it sends me the whole data stream which takes about 15 minutes to read. So my question: is there any method I can use to get one specified register's value using his OBIS code (1.1.1.8.0.255 - active energy taken) in java via TCP server?
import java.net.*;
import java.io.*;
public class scratch {
public static void main(String[] args) {
String hostname = "ip (hidden)";
int port = port (hidden);
try (Socket socket = new Socket(hostname, port)) {
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
int character;
StringBuilder data = new StringBuilder();
String test = "/?!\r\n";
byte[] req = test.getBytes();
out.write(req);
while ((character = reader.read()) != '\n') {
data.append((char) character);
}
System.out.println(data);
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
The message "test" send initiation request to meter and his respond is correct but I dont' know how to put flags (ACK STX ETX) in my request, I've tried something like this:
String test2 = (char)0x6 + "051\r\n";
byte[] req2 = test2.getBytes("ASCII");
out.write(req2);
But meter doesn't recognize it.
I am making a chat program. The problem occurs during the connection phase. Theoretically, the connection happens this way:
[Server] accept() incoming connection
[Client] attempt connection to the server
[Server & Client] initialize IO
[Client] send the username with a suffix indicating if there is or not a password following
[Server] receive username, check if there is an incoming password (if there is, read it too)
[Server] Check in database if client is already registered
[Server] ... (multiple checks of the client's account, etc...)
[Server] send an answer to the client if he is accepted or not
[Client] receive the answer and interpret it
Note that steps 6 and 7 are not yet implemented and the server skips to directly creating a new client account and accepting it in the network.
Now, something happens at either step 4 (if the error comes from the client not sending it's name) or at step 5 (if the error comes from the server not receiving the name), in either case, the server gets stuck waiting for the client's name and the client gets stuck waiting for the server's answer (step 9). I am asking your help in finding the cause of this bug and how to fix it.
Here is the code of the function used by the server to accept new connections:
public void establishConnection() {
Socket client = null;
BufferedReader input = null;
PrintWriter output = null;
String name = null;
String password = null;
try {
client = server.accept();
System.out.println("A connection is being established");
input = new BufferedReader(new InputStreamReader(client.getInputStream()));
output = new PrintWriter(client.getOutputStream());
//LOCATION OF THE BUG
//DESCRIPTION: If the name has been sent, the server seems not to receive it.
System.out.println("Waiting for the client's name...");
name = input.readLine();
if (name.charAt(name.length() - 1) == Keywords.PASSWORD) {
System.out.println("Waiting for the client's password...");
password = input.readLine();
} else
System.out.println("The client has no password");
name = name.substring(0, name.length() - 1);
System.out.println("Creation of the metaClient");
MetaClient metaClient = new MetaClient(name);
if (password != null)
metaClient.setPassword(password);
metaClient.setSocket(client);
System.out.println("Activating listening thread");
metaClient.activateCommunications(this, this);
/* If there is no already registered clients,
* the first to connect shall be the owner.
*/
if (clientsList.size() == 0)
metaClient.addRight(MetaClient.OWNER);
clientsList.add(metaClient);
output.write(Keywords.CONNECTION_ACCEPTED);
System.out.println("The connection process of user " + metaClient.getName()
+ " is complete.");
} catch (IOException e) {
System.out.println("Error when establishing a new connection");
e.printStackTrace();
} finally {
try {
if (input != null)
input.close();
if (output != null)
output.close();
} catch (IOException e) {
System.out.println("Error when closing the IO of the new connection.");
e.printStackTrace();
}
}
}
Here is the code of the builder of the client that tries to connect to the server:
public ChatClient(String ip, int port, String name, String password) throws ConnectException {
this.name = name;
boolean connectionRefused = false;
try {
System.out.println("Establishing connection to the server...");
server = new Socket(ip, port);
BufferedReader input = new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter output = new PrintWriter(server.getOutputStream());
//LOCATION OF THE BUG:
//BUG DESCRIPTION: The name seems not to be sent to the server
System.out.println("Sending name to the server...");
if (password == null || password == "") {
name += Keywords.NO_PASSWORD;
output.println(name);
} else {
name += Keywords.PASSWORD;
output.println(name);
System.out.println("Sending password to the server...");
output.println(password);
}
System.out.println("Waiting for the server's response...");
//Wait for the server's response
String response = input.readLine();
if (response.equals(Keywords.CONNECTION_ACCEPTED))
System.out.println("The connection has been accepted");
else
connectionRefused = true;
} catch (IOException e) {
System.out.println("Error when connecting to the server");
e.printStackTrace();
System.exit(1);
}
if (connectionRefused)
throw new ConnectException("The connection was refused by the server");
else {
communication = new CommunicationProtocol(server, this, this);
communication.start();
}
}
Any help would be really much appreciated, it makes quite some time now that i'm trying to fix this to no avail.
Edit to answer Scary Wombat's comment:
Yes, one machine runs the server and another runs the client. But the error happens even when both are running as two separate programs on one machine.
I am trying to create a simple socket based server/client communication between a Java-based socket server and PHP-based socket client. I am getting all the responses as expected but not immediately. Here is what I am trying to do. PHP client sends a command to the Java server, it responds back with an answer. This answer should be displayed on PHP page immediately. Then a second command is sent and again, the server sends a response which should be displayed immediately. However in my case, the responses are 'echoed' only after entire socket based communication is terminated. That is after I close the socket connection from PHP client.
Following is my Java Socket Server code:
public class MultiThreadServer implements Runnable {
Socket csocket;
MultiThreadServer(final Socket csocket) {
this.csocket = csocket;
}
private static void download(final String url) {
try {
final URL downloadURL = new URL(url);
URLConnection conn = null;
try {
conn = downloadURL.openConnection();
final InputStream inputStream = conn.getInputStream();
final long filesize = conn.getContentLength();
System.out.println("Size of file : " + (filesize / 1024)
+ " (kb)");
final FileOutputStream outputStream = new FileOutputStream(
System.getProperty("user.dir") + "/test.exe");
final long startTime = System.currentTimeMillis();
final byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
final long endTime = System.currentTimeMillis();
System.out.println("File downloaded");
System.out.println("Download time in sec. is : "
+ ((endTime - startTime) / 1000));
outputStream.close();
inputStream.close();
} catch (final IOException e) {
e.printStackTrace();
}
} catch (final MalformedURLException e) {
e.printStackTrace();
}
}
public static void main(final String args[]) throws Exception {
final ServerSocket ssock = new ServerSocket(3333);
System.out.println("Listening on " + ssock.toString());
while (true) {
final Socket sock = ssock.accept();
System.out.println("Connected to " + sock.getRemoteSocketAddress());
new Thread(new MultiThreadServer(sock)).start();
}
}
#Override
public void run() {
try {
final BufferedReader br = new BufferedReader(new InputStreamReader(
this.csocket.getInputStream()));
final BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(this.csocket.getOutputStream()));
bw.write(this.csocket.getRemoteSocketAddress().toString()
.replace("/", "")
+ "\n");
bw.flush();
String line;
while ((line = br.readLine()) != null) {
if (line.equalsIgnoreCase("getMacName")) {
final String macName = InetAddress.getLocalHost()
.getHostName();
bw.write(macName + "\n");
bw.flush();
System.out.println("Machine Name : " + macName);
} else if (line.equalsIgnoreCase("getMacIP")) {
final String macIP = InetAddress.getLocalHost()
.getHostAddress();
bw.write(macIP + "\n");
bw.flush();
System.out.println("Machine IP : " + macIP);
} else if (line.equalsIgnoreCase("getCurrentVersion")) {
final String currVersion = "0.1a";
bw.write(currVersion + "\n");
bw.flush();
System.out.println("Current Version : " + currVersion);
} else if (line
.equalsIgnoreCase("downUrl:http://webserver/webapp/test.exe")) {
final String url = line.substring(8);
bw.write("Downloading : " + url + "\n");
bw.flush();
MultiThreadServer.download(url);
System.out.println("URL : " + url);
} else if (line.equalsIgnoreCase("exit")) {
bw.write("Closing\n");
bw.flush();
bw.close();
br.close();
System.out.println("Exiting!");
this.csocket.close();
break;
}
}
} catch (final IOException e) {
e.printStackTrace();
}
}
}
Following is my sample PHP client source code:
<html>
<head>
<title>Socket Connection Test</title>
</head>
<body>
<h3>Testing Socket Connection</h3>
<br>
<?php
$host="127.0.0.1";
$port = 3333;
$fp;
$macName;
$macIP;
$message;
$result;
// open a client connection
$fp = fsockopen ($host, $port, $errno, $errstr);
if (!$fp)
{
$result = "Error: Could not open socket connection! Error No: " . $errno . ". Error String: " . $errstr;
die($result);
}
else
{
$message = fgets ($fp, 1024);
$message = trim($message);
echo "Connected to remote server on current port : " . $message;
echo "<br>";
sleep(5);
// get machine name
fwrite ($fp, "getMacName\n");
$macName = fgets ($fp, 1024);
$macName = trim($macName);
echo "Machine Name : " . $macName;
echo "<br>";
sleep(5);
// get IP address
fwrite ($fp, "getMacIP\n");
$macIP = fgets ($fp, 1024);
$macIP = trim($macIP);
echo "Machine IP : " . $macIP;
echo "<br>";
sleep(5);
fwrite ($fp, "getCurrentVersion\n");
$currVersion = fgets ($fp, 1024);
$currVersion = trim($currVersion);
echo "Current Version : " . $currVersion;
echo "<br>";
sleep(5);
fwrite ($fp, "downUrl:http://webserver/webapp/text.exe\n");
$downResponse = fgets ($fp, 1024);
$downResponse = trim($downResponse);
echo "Download Response : " . $downResponse;
echo "<br>";
sleep(5);
fwrite ($fp, "exit\n");
$exitStatus = fgets ($fp, 1024);
fclose ($fp);
echo "Connection Closed.";
}
?>
</body>
</html>
In this case, the entire PHP output is displayed at the end. I even tried putting sleeps at various places, however it seems to be waiting for socket connection to be closed before writing the output. How can I can I get the output "LIVE". Like a normal chat communication? What am I doing wrong here?
Your script works okay, and has no big flaws for what you're looking for. Since you obtain the desired result when you run the script from command line rather than a web browser, we can pinpoint the cause of the issue: the HTTP protocol
HTTP isn't made for sustained connections (like you're used to with Java sockets) but it's simplified workflow is based along the lines of Request/Elaborate/Response/Forget. Therefore, you can't have a "live chat" with a pure HTML/PHP over HTTP solution.
Alas, not all your hopes are lost! To implement a "live" communication you can use Ajax, which isn't too hard to get used to. I've said "live" because it's still an HTTP based solution, but at least you can have requests and receive responses from within the same webpage, which is the closest you can get with the HTML/PHP/AJAX triad.
It seems you dont understand php with http well .
You will get the HTML response only after your php client code completes execution. (i.e) all your echo's will be put in place where you specified and returned as a whole.
Putting sleep will only delay the execution.
i'm trying to convert a simple irc client written on java to blackberry, it uses sockets, here it is:
package seinao;
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
// The server to connect to and our details.
String server = "127.0.0.1";
String nick = "nickname";
String login = "nickname";
// The channel which the bot will join.
String channel = "#oi";
// Connect directly to the IRC server.
Socket socket = new Socket(server, 6667);
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream( )));
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream( )));
// Log on to the server.
writer.write("NICK " + nick + "\r\n");
writer.write("USER " + login + " 8 * : Java IRC Hacks Bot\r\n");
writer.write("Hello World!");
writer.write("PRIVMSG " + channel + "Hello!\r\n");
writer.flush( );
// Read lines from the server until it tells us we have connected.
String line = null;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
System.out.println("Nickname is already in use.");
return;
}
}
// Join the channel.
writer.write("JOIN " + channel + "\r\n");
writer.flush( );
// Keep reading lines from the server.
while ((line = reader.readLine( )) != null) {
if (line.toLowerCase( ).startsWith("PING ")) {
// We must respond to PINGs to avoid being disconnected.
writer.write("PONG " + line.substring(5) + "\r\n");
writer.write("PRIVMSG " + channel + " :I got pinged!\r\n");
writer.flush( );
}
else if(line.toLowerCase( ).contains("funciona")){
writer.write("PRIVMSG " + channel + " Olaz!\r\n");
writer.flush();
System.out.println("mermao ta foda");
}
else {
// Print the raw line received by the client.
System.out.println(line);
}
}
}
}
but i noticed there is no java.net.* on blackberry eclipse plugin soo, what should I do ? can someone help me ? what should I use for sockets ? I'm new to java and blackberry programming but i'm learning it quite fast, thanks alot
If I remember correctly, it's SocketConnection that you use. Search through the Blackberry API for what you'll need, it'll be way more helpful.