I'm programming a Bitcoin miner that mines in a pool using the stratum protocol (see documentation here.
The stratum protocol uses JSON-RPC 2.0 as it's encoding and according to the JSON-RPC 2.0 specification(specification here) I should use sockets to create a connection to the pool.
My problem is that I don't seem to be able to receive a response back from the pool. JSON-RPC 2.0 states that for every Request object that I send, I must receive a response back.
Here is my code:
public static void main(String[] args)
{
connectToPool("stratum.slushpool.com", 3333);
}
static void connectToPool(String host, int port)
{
try
{
InetAddress address = InetAddress.getByName(host);
out.println("Atempting to connect to " + address.toString() + " on port " + port + ".");
socket = new Socket(address, port);
String message1 = "{\"jsonrpc\" : \"2.0\", \"id\": 1, \"method\": \"mining.subscribe\", \"params\": []}";
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.write((message1 + "\\n"));
out.println(input.readLine());//Hangs here.
}
catch (IOException e)
{
out.println(e.getMessage());
out.println("Error. Can't connect to Pool.");
System.exit(-2);
}
}
After hours of tinkering around I have found the solution.
Apparently the JSON string shouldn't have any spaces. So instead of:
String message1 = "{\"jsonrpc\" : \"2.0\", \"id\": 1, \"method\": \"mining.subscribe\", \"params\": []}";
It should be:
String message1 = "{\"id\":1,\"method\":\"mining.subscribe\",\"params\":[]}";
Ok guys .. this is the full running code. Enjoy.
import java.io.PrintWriter;
import java.net.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class StratumSubscribe {
public static void main(String[] args)
{
connectToPool("sha256.hk.nicehash.com", 3334);
}
static void connectToPool(String host, int port)
{
try
{
InetAddress address = InetAddress.getByName(host);
System.out.println("Atempting to connect to " + address.toString() + " on port " + port + ".");
Socket socket = new Socket(address, port);
String message1 = "{\"id\":1,\"method\":\"mining.subscribe\",\"params\":[]}";
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println((message1));
System.out.println(input.readLine());//Hangs here.
}
catch (IOException e)
{
System.out.println(e.getMessage());
System.out.println("Error. Can't connect to Pool.");
System.exit(-2);
}
}
}
Related
I am trying to send a message from publisher file (sending on port 8000) which is received by Server (listening on port 5000 and 8000)and which forwards the message to the subscriber(listening on port 5000). The problem is that, communication between publisher and server is fine, however, I am not able to forward the message to the subscriber because the server is still listening to publisher and toggling to the subscriber port and forwarding the message. Any suggestion is appretiated
Publisher
package serverclient;
import java.net.*;
import java.io.*;
public class Publisher {
public static void main (String [] args) throws IOException{
Socket sock = new Socket("127.0.0.1",8000);
// reading from keyboard (keyRead object)
BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
// sending to client (pwrite object)
OutputStream ostream = sock.getOutputStream();
PrintWriter pwrite = new PrintWriter(ostream, true);
InputStream istream = sock.getInputStream();
BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));
System.out.println("Start the chitchat, type and press Enter key");
String receiveMessage,sendMessage;
while(true)
{
sendMessage = keyRead.readLine(); // keyboard reading
pwrite.println(sendMessage); // sending to server
pwrite.flush(); // flush the data
if((receiveMessage = receiveRead.readLine()) != null) //receive from server
{
System.out.println(receiveMessage); // displaying at DOS prompt
}
else{
System.out.print("Null");
}
}
}
}
Subscriber
package serverclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class Subscriber {
public static void main (String [] args) throws IOException{
Socket sock = new Socket("127.0.0.1",5000);
// receiving from server ( receiveRead object)
InputStream istream = sock.getInputStream();
BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));
System.out.println("Recive side");
System.out.print("Connection Status: " + sock.isConnected() + " " + sock.getPort());
String receiveMessage, sendMessage;
while(true)
{
System.out.print("Hey man " + receiveRead.readLine() + "\n");
if((receiveMessage = receiveRead.readLine()) != null) //receive from server
{
System.out.println(receiveMessage); // displaying at DOS prompt
break;
}
else{
System.out.print("Null");
}
}
}
}
Server
package serverclient;
import java.io.*;
import java.net.*;
public class Server extends Thread{
private Socket socket;
private int clientNumber;
public Server(Socket socket, int clientNumber){
this.socket = socket;
this.clientNumber = clientNumber;
if(socket.getLocalPort() == 5000)System.out.print("\nSubscriber "+ clientNumber +" is connected to the server");
if(socket.getLocalPort() == 8000)System.out.print("\nPublisher "+ clientNumber +" is connected to the server");
}
#Override
public void run(){
try {
BufferedReader dStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.print("\nSocket Address "+ socket.getLocalPort() + " " + socket.getPort());
while(true){
if ( socket.getInputStream().available() != 0 && socket.getLocalPort() == 8000 ){
synchronized(this){
String clMessage = dStream.readLine();
System.out.println(clMessage);
out.println("Hey the publisher has sent the message : " + clMessage);
}
}else if (socket.getInputStream().available() != 0 && socket.getLocalPort() == 5000 ){
out.println("Hey man I am so good");
}
}
} catch (IOException ex) {
System.out.print("\nError has been handled 1\n");
}finally{
try {
socket.close();
} catch (IOException ex) {
System.out.print("\nError has been handled 2\n");
}
}
}
public static void main(String [] args) throws IOException{
int subNumber = 0;
int pubNumber = 0;
ServerSocket servSockpub = new ServerSocket(8000);
ServerSocket servSocksub = new ServerSocket(5000);
try {
while (true) {
Server servpub = new Server(servSockpub.accept(),++pubNumber);
servpub.start();
System.out.print("\nThe server is running on listen port "+ servSockpub.getLocalPort());
Server servsub = new Server(servSocksub.accept(),++subNumber);
servsub.start();
System.out.print("\nThe server is running on listen port "+ servSocksub.getLocalPort());
}
} finally {
servSockpub.close();
servSocksub.close();
}
}
}
I see nothing wrong with the server ports (no duplicates/collisions).
But you have no code whatsoever that bridges data between the 2 sockets.
Basically, you should have 1 server that receives the 2 sockets and move data across in1-out2.
Careful too, in your code you can only connect a subscriber once the publisher has connected.
I'm trying to get a basic client working to learn Sockets and for some reason, i can't seem to create a Socket object though the docs say it should be able to take a String, int combo. Did I mess up somewhere?
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class JokeClient {
public static void main(String[] args) {
// Ensures they have to have a length of 2
int PORT_NUM = 3363;
String ipAddress = "127.0.0.1";
if (args.length == 2) {
PORT_NUM = Integer.parseInt(args[1]);
ipAddress = args[0];
}
else {
if (args.length > 0) {
System.err.println("programName <ipAddress/hostname> <portNum>");
System.exit(1);
}
else
System.out.println("Assuming you want defaults of IP Address: " + ipAddress + "\nPort Number: " + PORT_NUM);
}
System.out.println("Setting up client...");
Scanner textIn = new Scanner(System.in);
try {
Socket clientSock = Socket(ipAddress, PORT_NUM);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (Exception e) {
System.out.println("Error connecting to: " + ipAddress + " on:" + PORT_NUM + "\nError: " + e);
}
}
}
The creation of clientSocket is the problem with the instantiation I am trying. Am I using the wrong Socket?
Constructing an instance of a class requires the new keyword:
Socket clientSocket = new Socket(ipAddress, PORT_NUM);
Otherwise the compiler will consider it as a normal method instead of a constructor.
I'm a beginner (as you can probably tell) and I'm having issues establishing a connection from my very simple client to my very simple server. My server starts up fine as it creates a serversocket that listens on port 43594. However, when I run my client to try to establish a connection, an IOException is thrown by my client as it tries to connect.
I'm doing java in my spare time as a hobby, so I'd really appreciate if someone could help me understand what's going on, where I'm going wrong (or if I'm even going right any where) so as to help me improve.
Here is my Server code:
package src.org;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.*;
import java.io.*;
public class Server {
private static final Logger logger = Logger.getLogger(Server.class.getName());
private final static void createSocket(int portNumber) throws IOException
{
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public static void main(String... args)
{
logger.info("Starting server...");
Properties properties = new Properties();
logger.info("loading settings...");
try
{
properties.load(new FileInputStream("settings.ini"));
Constants.GAME_NAME = properties.getProperty("name");
Constants.PORT = Integer.valueOf(properties.getProperty("port"));
} catch(Exception ex)
{
ex.printStackTrace();
}
logger.info("Creating sockets...");
try
{
logger.info("Socket created. Listening on port: " + Constants.PORT);
createSocket(Constants.PORT);
} catch(Exception ex)
{
logger.log(Level.SEVERE, "Error creating sockets.", ex);
System.exit(1);
}
}
}
Which (to my knowledge) seems to be doing its job.
And here's what I believe to be the culprit class, the client class:
import java.io.*;
import java.net.*;
public class Client {
//private static final String hostName = Constants.HOST_NAME;
//private static final int portNumber = Constants.PORT;
private static final String hostName = "localhost";
private static final int portNumber = 43594;
public static void main(String... args)
{
try (
Socket socket = new Socket(InetAddress.getLocalHost(), portNumber); // using localhost at the moment
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
System.out.println("Client socket created.");
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer, fromUser;
while((fromServer = in.readLine()) != null)
{
System.out.println("Server:" + fromServer);
fromUser = stdIn.readLine();
if(fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
} catch(UnknownHostException ex) {
System.err.println("Unknown host: " + hostName);
System.exit(1);
} catch(IOException ioe) {
System.err.println("Couldn't get i/o from: " + hostName);
System.out.println("Error:" + ioe.getMessage());
System.exit(1);
}
}
}
When I ping localhost I get a response; the port on both sides is 43594 and the host is just local. The command line response from the client is:
Client socket created
Couldn't get i/o from: localhost
Error: connection reset
Press any key to continue...
I'm sorry in that I know this would be a very simple fix to many of you, but I can't seem to find an answer or fix it myself. Any insight or help would be greatly appreciated. Cheers.
Sorry if I've left out any other important pieces of information.
You've left out much of the code. The part in the server that sends data on the accepted socket. So the method that calls accept() just exits, the socket is garbage-collected, and closed, and the client keeps doing I/O to the other end of the connection, which is invalid,so you get an exception.
Is there a way I could create an array of network streams in java. C# supports creation of an array of Network Streams.
AFAIK we need to create separate InputStreams and OutputStreams in order to receive and send data in Java.
What I want to do is to make a number of TCP connections to send and receive data.
Is there a work around in java for this?
You can achieve that by creating multiple instances of Socket as follows:
Server.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
{
private static int CLIENT_COUNT = 0;
public static void main(String[] args) throws IOException
{
ServerSocket ss = new ServerSocket(2000);
while(true)
{
Socket s = ss.accept();
new SocketHandler("Handler#" + ++CLIENT_COUNT, s).start();
}
}
}
class SocketHandler extends Thread
{
private PrintWriter pw;
private BufferedReader br;
public SocketHandler(String name, Socket socket) throws IOException
{
super(name);
this.pw = new PrintWriter(socket.getOutputStream(), true);
this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
#Override
public void run()
{
String message;
try
{
while((message = br.readLine()) != null)
{
System.out.println("Server#" + getName() + " - Client sent: " + message);
sendMessage("Server#" + getName() + ": echo " + message);
}
}
catch(IOException e)
{
e.printStackTrace();
System.out.println("Server#" + getName() + " -> IOException");
}
}
public void sendMessage(String message)
{
pw.println(message);
System.out.println("Server#" + getName() + " is sending ~ " + message);
}
}
Client.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client
{
private static int SOCKET_COUNT = 0;
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket s1 = new Socket(InetAddress.getLocalHost(), 2000);
Socket s2 = new Socket(InetAddress.getLocalHost(), 2000);
Socket s3 = new Socket(InetAddress.getLocalHost(), 2000);
Socket s4 = new Socket(InetAddress.getLocalHost(), 2000);
LocalSocketHandler h1 = new LocalSocketHandler("LocalHandler#" + ++SOCKET_COUNT, s1);
LocalSocketHandler h2 = new LocalSocketHandler("LocalHandler#" + ++SOCKET_COUNT, s2);
LocalSocketHandler h3 = new LocalSocketHandler("LocalHandler#" + ++SOCKET_COUNT, s3);
LocalSocketHandler h4 = new LocalSocketHandler("LocalHandler#" + ++SOCKET_COUNT, s4);
h1.start();
h2.start();
h3.start();
h4.start();
h1.sendMessage("I am socket #1!");
h2.sendMessage("I am socket #2!");
h3.sendMessage("I am socket #3!");
h4.sendMessage("I am socket #4!");
}
}
class LocalSocketHandler extends Thread
{
private PrintWriter pw;
private BufferedReader br;
public LocalSocketHandler(String name, Socket socket) throws IOException
{
super(name);
this.pw = new PrintWriter(socket.getOutputStream(), true);
this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
#Override
public void run()
{
String message;
try
{
while((message = br.readLine()) != null)
{
System.out.println("Client#" + getName() + " - Server sent: " + message);
}
}
catch(IOException e)
{
e.printStackTrace();
System.out.println("Client#" + getName() + " -> IOException");
}
}
public void sendMessage(String message)
{
pw.println(message);
System.out.println("Client#" + getName() + " is sending ~ " + message);
}
}
Client's console:
Client#LocalHandler#1 is sending ~ I am socket #1!
Client#LocalHandler#2 is sending ~ I am socket #2!
Client#LocalHandler#3 is sending ~ I am socket #3!
Client#LocalHandler#4 is sending ~ I am socket #4!
Client#LocalHandler#1 - Server sent: Server#Handler#1: echo I am socket #1!
Client#LocalHandler#3 - Server sent: Server#Handler#3: echo I am socket #3!
Client#LocalHandler#2 - Server sent: Server#Handler#2: echo I am socket #2!
Client#LocalHandler#4 - Server sent: Server#Handler#4: echo I am socket #4!
Server's console:
Server#Handler#1 - Client sent: I am socket #1!
Server#Handler#1 is sending ~ Server#Handler#1: echo I am socket #1!
Server#Handler#3 - Client sent: I am socket #3!
Server#Handler#3 is sending ~ Server#Handler#3: echo I am socket #3!
Server#Handler#2 - Client sent: I am socket #2!
Server#Handler#2 is sending ~ Server#Handler#2: echo I am socket #2!
Server#Handler#4 - Client sent: I am socket #4!
Server#Handler#4 is sending ~ Server#Handler#4: echo I am socket #4!
EDIT: Ik it is long but does anyone know how to program sockets??
My problem is confusing me a bit. I have a server running on one computer and on another, I have a client connected to it. When I type a message from the client into the console and send it, the server does not seem to receive it. Anybody know why because I have been testing with printing to the console for the last 3 hours and cannot figure this out. I am relatively new to sockets so don't be too harsh if I am just being an idiot.
Heres my code for the client side:
import java.net.*;
import java.util.Scanner;
import java.io.*;
public class SocketClient {
public static void main(String [] args) {
String host = "************";
int port = 25565;
StringBuffer instr = new StringBuffer();
String TimeStamp;
System.out.println("SocketClient initialized");
try {
InetAddress address = InetAddress.getByName(host);
Socket connection = new Socket(address, port);
BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
Scanner scan = new Scanner(System.in);
String message = scan.nextLine();
TimeStamp = new java.util.Date().toString();
String process = "Server called on " + host + ":" + port + " at " + TimeStamp + ": " + message + (char) 13;
osw.write(process);
osw.flush();
BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
InputStreamReader isr = new InputStreamReader(bis, "US-ASCII");
int c;
while ( (c = isr.read()) != 13)
instr.append( (char) c);
connection.close();
System.out.println(instr);
} catch (UnknownHostException e) {
System.err.println("UnknownHostException: " + e);
} catch (IOException e) {
System.err.println("IOExcepion: " + e);
}
}
}
Here is the code to connect the client to the server:
import java.io.IOException;
import java.net.*;
public class MultipleSocketServer {
public static Socket connection;
public static String name = "Tyler's Server";
public static int limit = 2;
public static Thread[] clients = new Thread[limit];
public static int current = 0;
public static int port = 25565;
public static String[] connected = {"", ""};
public static ServerSocket socket;
public static void main(String[] args) {
System.out.println("Server starting...");
try {
ServerSocket socket = new ServerSocket(port);
while(true) {
Socket connection = socket.accept();
String ip = connection.getRemoteSocketAddress().toString().substring(1, 13);
loop:
for(int i = 0; i < connected.length; i++) {
if(connected[0].equals(ip) || connected[1].equals(ip)) {
break loop;
}else if(!connected[i].equals(ip)) {
connected[i] = ip;
System.out.println(ip);
MultiServer_Client client = new MultiServer_Client(connection, i);
Thread run = new Thread(client);
run.start();
break loop;
}
}
}
} catch (IOException e1) {
System.out.println("Could not bind server on: " + port);
System.exit(-1);
}
}
}
And here is my code to handle each client as connected:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class MultiServer_Client implements Runnable {
public String time;
public Socket client;
public StringBuffer process = new StringBuffer();
public BufferedInputStream inputStream;
public InputStreamReader reader;
public BufferedOutputStream outputStream;
public OutputStreamWriter writer;
public boolean connected = true;
public int ID;
public MultiServer_Client(Socket connection, int i) {
client = connection;
ID = i;
try {
inputStream = new BufferedInputStream(client.getInputStream());
reader = new InputStreamReader(inputStream);
outputStream = new BufferedOutputStream(client.getOutputStream());
writer = new OutputStreamWriter(outputStream, "US-ASCII");
} catch (IOException e) {
System.out.println("IOException: " + e);
}
System.out.println("Client connected...");
write("Connected to " + MultipleSocketServer.name);
}
public void run() {
while(connected) {
write("hi");
}
System.out.println("Disconnecting client...");
}
public void write(String authen) {
try {
time = new java.util.Date().toString();
String message = time + ": " + authen + (char) 13;
writer.write(message);
writer.flush();
} catch (IOException e) {
connected = false;
MultipleSocketServer.connected[ID] = "";
}
}
public void read() {
//read from client
int character;
process = new StringBuffer();
try {
while ((character = reader.read()) != 13) {
process.append((char) character);
}
System.out.println(process);
process.delete(0, process.length());
} catch (IOException e) {
connected = false;
MultipleSocketServer.connected[ID] = "";
}
}
}
Srry if I cannot help very much. As I said, I am new to sockets and no one else seems to have any problems with this... Thanks :)
The problem with your code is not the "sockets" its your communication protocol. You are effectively closing the socket before the server has a chance to write out "hi".
To debug this, you want to reduce the complexity of your program. There are a number of things that don't make any sense or matter in your program.
So, a little background on Sockets. There are two types of sockets. A "ServerSocket" and a "Socket" The ServerSocket is sort of like a secretary. Its only job is to listen for calls and then pass them on. This is what the "accept" does. Before any client connects, the accept() will block until it receives a connection. Once the client connects, the accept returns a Socket representing the connection.
The regular Socket is where all the work occurs. You can think of it as a telephone connection. You can talk to someone remotely with the OutputStream, and listen using the InputStream. The challenge is that you need to create some sort of communication (called a protocol) for your two sockets to communicate.
You need to figure out how you want to delimit your commands. You could pass a fixed length number and then the data if you want a "length" delimited protocol or you could use a special character for the end of the message (what you currently have). For the quick and dirty, I often use the latter with a newline character. The easiest is to just use a PrintWriter for writing and a Scanner for reading.
The next step is to figure out the communication pattern for the client and the server. Think if it as passing a ball back and forth. If the client says something, the other side should be listening (and vice versa).
Once the protocol and logic is figured out, you can then move the logic for "handling" the server side into separate threads (called a worker pattern) so that the server can handle more than one client at a time. If you want to go even further, you can implement a reactor with a thread pool so that the server doesn't run out of threads, but that is probably for another day/question.
I would recommend following the Java tutorial on Sockets: http://docs.oracle.com/javase/tutorial/networking/sockets/index.html