I'm currently working on a tiny individual project for this semester with Android. What I'm going to do is making lots of connections to my https server with my Android phone so the server goes down. I know absolutely nothing about programming because I'm studying networking not computer language. But I somehow collected from here and there piece by piece and made a code like below. I think it's using a socket connection.
import java.net.*;
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HTTPSClient {
public static void main(String[] args) {
System.out.println("Usage: java HTTPSClient host");
int port = 443; // default https port
String host = "192.168.0.8";
TrustManager[] trustAll = new javax.net.ssl.TrustManager[]{
new javax.net.ssl.X509TrustManager(){
public java.security.cert.X509Certificate[] getAcceptedIssuers(){
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs,String authType){}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs,String authType){}
}
};
try {
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAll, new java.security.SecureRandom());
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
SSLSocketFactory factory = (SSLSocketFactory) sc.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
Writer out = new OutputStreamWriter(socket.getOutputStream());
out.write("GET / HTTP/1.0\\r\\n");
out.write("\\r\\n");
out.flush();
// read response
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
int c;
while ((c = in.read()) != -1) {
System.out.write(c);
}
// out.close();
// in.close();
// socket.close();
} catch (Exception e) {
System.err.println(e);
}
}
}
I enabled https on my macbook and I can see the port 443 listening. When I execute the code above I can see one established connection through 'netstat -an | grep 443' until I stop it. My question is this: if I want to make multiple connection with this code, what should I add on? Is it possible with this code? My idea is that if I can see heaps of established connections to 443 port on my macbook, I will not be able to connect https:://localhost with a browser because the machine is down. I don't know if it's correct but I hope. Because the semester is almost over and I anyway have to make something to report.
I'm not sure if that code will be the same when I make the code for Android phone but I just want to see something happening first. I'm really desperate, please help me. Thank you very much.
From what I can understand, you are trying to have multiple clients(phones) connect to your server.
Your server looks solid. You should be able to modify it to handle multiple clients easily.
Generally you need a handler of some sort to process incoming client connections. You will need a loop to wait for new connections, and then a thread to handle each connection independently. Each instance of a socket can only handle one connection. A socket factory allows you to bind more than once instance of a socket to the server. I have two classes to handle multiple connections. My first class is the server itself and the second is a a thread to handle each client.
If you are not familiar with threading, you should check into it.
This is the server class:
public class ServerThread extends Thread
{
private Vector<ClientHandlerThread> connectedClients = new Vector<ClientHandlerThread>(20, 5);
public void run()
{
SSLServerSocket sslDataTraffic = null;
SSLServerSocket sslFileTraffic = null;
SSLServerSocketFactory sslFac = null;
try
{
System.out.print("Validating SSL certificate... ");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(certificateDir), password);
System.out.println("DONE.");
System.out.print("Creating trust engine........ ");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
System.out.println("DONE.");
System.out.print("Creating key engine.......... ");
KeyManagerFactory kmf = KeyManagerFactory.getInstance((KeyManagerFactory.getDefaultAlgorithm()));
kmf.init(keyStore, password);
System.out.println("DONE.");
System.out.print("Creating SSL context......... ");
System.setProperty("https.protocols", "SSL");
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
sslFac = ctx.getServerSocketFactory();
System.out.println("DONE.");
}
catch (Exception e) {}
try
{
System.out.print("Creating data socket......... ");
sslDataTraffic = (SSLServerSocket) sslFac.createServerSocket(dataPort);
System.out.println("DONE. Est. on:" + dataPort);
}
catch (IOException e)
{
System.out.println("FAILED.");
System.out.println(e.toString() + " ::: " + e.getCause());
System.exit(-1);
}
try
{
System.out.print("Creating file socket......... ");
sslFileTraffic = (SSLServerSocket) sslFac.createServerSocket(filePort);
System.out.println("DONE. Est. on:" + filePort);
}
catch (IOException e)
{
System.out.println("FAILED.");
System.out.println(e.toString() + " ::: " + e.getCause());
System.exit(-1);
}
while (running)
{
SSLSocket sslDataTrafficSocketInstance = (SSLSocket) sslDataTraffic.accept();
SSLSocket sslFileTrafficSocketInstance = (SSLSocket) sslFileTraffic.accept();
ClientHandlerThread c = new ClientHandlerThread(sslDataTrafficSocketInstance, sslFileTrafficSocketInstance);
c.start();
connectedClients.add(c);
}
}
Notice the while loop at the end of the class. It will wait until a client connects (which invokes the accept() method). An independent thread is created to handle that client (phone).
The client thread is as follows:
public class ClientHandlerThread extends Thread
{
private boolean running = true;
private SSLSocket dataSocket;
private SSLSocket fileSocket;
private PrintWriter writer;
private BufferedReader reader;
private InputStream inputStream;
private OutputStream outputStream;
public ClientHandlerThread(
SSLSocket dataSocket,
SSLSocket fileSocket)
{
this.dataSocket = dataSocket;
this.fileSocket = fileSocket;
try
{
this.reader = new BufferedReader(new InputStreamReader(this.dataSocket.getInputStream()));
this.writer = new PrintWriter(this.dataSocket.getOutputStream());
this.inputStream = fileSocket.getInputStream();
this.outputStream = fileSocket.getOutputStream();
}
catch (IOException e)
{
e.printStackTrace();
}
this.ip = this.dataSocket.getInetAddress().getHostAddress();
}
public void run()
{
try
{
writer.println("SERVER_HANDSHAKE_INIT");
writer.flush();
String fromClient;
while (running && (fromClient = reader.readLine()) != null)
{
if (fromClient.equals("CLIENT_HANDSHAKE_INIT"))
System.out.println("Client Connected: " + getIP());
}
}
catch (IOException e)
{
e.getCause();
}
}
public String getIP()
{
return ip;
}
public boolean isRunning()
{
return running;
}
public void setRunning(boolean running)
{
this.running = running;
}
}
You now have the ability to iterate through each client thread held within the Vector containing all clients. This will allow you to handle multiple clients and interact with each of them independently. This includes reading input/output streams.
These classes are stripped down versions of the ones I use for a simple remote management system I developed over the summer. You should be able to modify them as necessary to meet your needs. You could add a parameter to the client thread constructor to keep track of naming for example.
I hope this explained how to handle multiple incoming connections to a server.
Feel free to DM or email me for additional info.
Cheers
You could change your code to open connections in a loop:
int numConnections = 100;
for (int i=0; i<numConnections; i++) {
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
Writer out = new OutputStreamWriter(socket.getOutputStream());
out.write("GET / HTTP/1.0\\r\\n");
out.write("\\r\\n");
out.flush();
// read response
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
int c;
while ((c = in.read()) != -1) {
System.out.write(c);
}
// out.close();
// in.close();
// socket.close();
}
I highly suggest retaining the socket objects in an array or collection variable and closing the I/O streams and socket when you are done, but this will also be done when main() exits - just know this is generally bad practice in programming if you were to want to reuse this code in a situation where the whole program didn't exit after the block of code that opens connection(s).
Related
I am trying to establish a SSL connection between java server and python client.
Here is the code:
Server side:
public class s implements Runnable {
List<SSLSocket> socketList= new ArrayList<SSLSocket>();
List<File> FileList= new ArrayList<File>();
List<Certificate> CertificateList = new ArrayList<Certificate>();
public static void main(String[] args) {
s manager = new s();
new Thread(manager).start();
Scanner scanner = new Scanner(System.in);
while(true){
System.out.printf("Send> ");
String message = scanner.nextLine();
if(message.equals("") || message.equals("/n")){
continue;
}else{
manager.send(message);
}
}
}
private static SSLServerSocket getServerSocket(int thePort)
{
SSLServerSocket s=null;
try
{
String key="G:\\mySrvKeystore";
char keyStorePass[]="123456".toCharArray();
char keyPassword[]="123456".toCharArray();
KeyStore ks= KeyStore.getInstance("JKS");
ks.load(new FileInputStream(key),keyStorePass);
KeyManagerFactory kmf= KeyManagerFactory.getInstance("SunX509");
kmf.init(ks,keyPassword);
SSLContext sslContext= SSLContext.getInstance("SSLv3");
sslContext.init(kmf.getKeyManagers(),null,null);
SSLServerSocketFactory factory=sslContext.getServerSocketFactory();
s=(SSLServerSocket)factory.createServerSocket(thePort);
}catch(Exception e)
{
System.out.println(e);
}
return(s);
}
public void run() {
try {
while (true) {
SSLServerSocket sslserversocket = getServerSocket(**9991**);
SSLSocket client = (SSLSocket)sslserversocket.accept();
socketList.add(client);
new Thread(new SSocket(client,socketList,FileList)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Client side:
class timer(threading.Thread):
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.ssl_sock = ssl.wrap_socket(self.sock, ssl_version=ssl.PROTOCOL_SSLv3)
self.ssl_sock.connect(('localhost',9990))
self.isrun = True
threading.Thread.__init__(self);
def run(self):
while self.isrun:
revice = self.ssl_sock.recv(1024);
print ("recv> " + revice);
self.sock.close();
self.ssl_sock.close();
def send(self,str):
self.ssl_sock.send(str + "\n")
def close(self):
self.isrun=False
if __name__=='__main__':
main()
I got:
I did not use reserve port and my OS is windows-7. And I run the server first then the client.
I don't understand why I cannot run multiple instance of the program?
Is it because I am using the same port?
But it was ok before when I just used socket instead of SSLsocket.
THanks for any help
You cannot have multiple server processes listening to the same port. How would the OS know which one gets the connection?
The usual way to handle multiple clients is to spawn a thread AFTER you have accepted a connection. You pass the connection to the thread and the main thread loops, continuing to listen and accept new connections.
This is all very basic TCP/IP and has nothing to do with SSL.
I am new to java and network programming for the most part. I want to write a program that automatically backs up my texts to my computer whenever my phone connects to my home wifi.
I am working on creating java classes that will handle sending data over the network. Using some questions found here, I came up with this implementation but I have some questions regarding some of the methods used in what I learned from.
Two Questions Regarding this code
I totally used a question from SO for the send methods in my client. The sendText uses a new thread, but the sendFile doesn't. Any particular reason why?
2. At which point in the code does the server actually know when there has been a message sent to the port? Is it at the method accept() call or is it when the BufferStream readLine() is checked? Does accept just grab data and throw it into the buffer? null implying the data grabbed was not a signal sent from a client?
Does the accept() method block execution of the code until a connection attempt is made from a client?
Thanks!
KServ
//Used to launch the server
public class KServ {
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java KServ <port number>");
System.exit(1);
}
int port = Integer.parseInt(args[0]);
KServer server = new KServer(port);
while (true) { //added this to keep the server polling for new data
server.run();
}
}
}
KServer
//Server class. Should handle data incoming
import java.net.*;
import java.io.*;
public class KServer {
private int port;
public KServer(int PORT) {
port = PORT;
}
public void run() {
try (
ServerSocket sSocket = new ServerSocket(port);
Socket cSocket = sSocket.accept();
PrintWriter out = new PrintWriter(cSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
) {
String input;
while ((input = in.readLine()) != null) {
System.out.println(input);
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port " + port + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
Client
//launches KClient object and uses it to send input from console to the server
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Usage: java Client <ip number> <port number>");
System.exit(1);
}
String ip = args[0];
int port = Integer.parseInt(args[1]);
KClient client = new KClient(ip,port);
String msg;
Scanner inStream = new Scanner(System.in);
while((msg = inStream.nextLine()).length() > 0) {
client.sendText(msg);
}
}
}
KClient
//Will be used to establish connection with server and send data from phone
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class KClient {
private String server;
private int port;
public KClient(String Server,int Port) {
server = Server;
port = Port;
}
public void sendFile(String fileName) {
File file = new File(fileName);
FileInputStream fileInputStream;
BufferedInputStream bufferedInputStream;
OutputStream outputStream;
try {
client = new Socket(server,port);
byte[] bytes = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(bytes, 0, bytes.length);
outputStream = client.getOutputStream();
outputStream.write(bytes,0,bytes.length);
outputStream.flush();
bufferedInputStream.close();
outputStream.close();
client.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket client;
private OutputStreamWriter outputStreamWriter;
public void sendText(String msg) {
System.out.println("Send Message!");
new Thread(new Runnable() {
#Override
public void run() {
try {
client = new Socket(server,port);
outputStreamWriter = new OutputStreamWriter(client.getOutputStream(), "ISO-8859-1");
outputStreamWriter.write(msg);
outputStreamWriter.flush();
outputStreamWriter.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
BufferedReader inStream;
public boolean Shake() {
try {
client = new Socket(server,port);
inStream = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
}
I totally used a question from SO for the send methods in my client. The sendText uses a new thread, but the sendFile doesn't. Any particular reason why?
Unanswerable. Ask the author. Both sends can block. As the file is presumably longer than the text, it would have made more sense to do it the other way round.
2. At which point in the code does the server actually know when there has been a message sent to the port? Is it at the method accept() call
No.
or is it when the BufferStream readLine() is checked?
Yes.
Does accept just grab data and throw it into the buffer?
No. It grabs a connection and returns it as a socket. Nothing to do with data whatsoever.
null implying the data grabbed was not a signal sent from a client?
You seem to be actually asking about BufferedReader.readLine() here, not ServerSocket.accept(), which doesn't return null. readLine() returns null when there is no pending data to be read and the peer has closed the connection.
Does the accept() method block execution of the code until a connection attempt is made from a client?
More or less. It blocks until there is a complete connection waiting to be accepted, which isn't quite the same thing, as there is a queue.
I will add that you have copied, or written, some truly terrible code here. There are much better examples.
I'm working on a program where multiple clients need to interact with a remote server.
I've tested it locally and everything's ok (sort of, more on that later), but I can't understand how to set a remote IP.
I read Socket's API and also InetAddress' API. Is this the right way to do it? How does Java deal with IPs? There are not just simple Strings as on the localhost case, am I right?
This is my code:
Client:
public class Client {
final String HOST = "localhost";
final int PORT = 5000;
Socket sc;
DataOutputStream message;
DataInputStream istream;
public void initClient() {
try {
sc = new Socket(HOST, PORT);
message = new DataOutputStream(sc.getOutputStream());
message.writeUTF("test");
sc.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Server:
public class Server {
final int PORT = 5000;
ServerSocket sc;
Socket so;
DataOutputStream ostream;
String incomingMessage;
public void initServer() {
try {
sc = new ServerSocket(PORT);
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
}
BufferedReader input;
while(true){
try {
so = new Socket();
System.out.println("Waiting for clients...");
so = sc.accept();
System.out.println("A client has connected.");
input = new BufferedReader(new InputStreamReader(so.getInputStream()));
ostream = new DataOutputStream(so.getOutputStream());
System.out.println("Confirming connection...");
ostream.writeUTF("Successful connection.");
incomingMessage = input.readLine();
System.out.println(incomingMessage);
sc.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
}
Also, I'm dealing with some troubles on my local tests.
First of all, some times I get the following result:
Waiting for clients...
A client has connected.
Confirming connection...
Error: Software caused connection abort: recv failed
Though some other times it works just fine. Well, that first connection at least.
Last question:
When I try to send a message from the server to the client, the program enters in an infite loop and need to be closed manually. I'm adding this to the code to do so:
fromServerToClient = new BufferedReader(new InputStreamReader(sc.getInputStream()));
text = fromServerToClient.readLine();
System.out.println(text);
Am I doing it right?
Thanks.
Instead of using
String host = "localhost";
you can use something like
String host = "www.ibm.com";
or
String host = "8.8.8.8";
this is how you would usually implement a Server:
class DateServer {
public static void main(String[] args) throws java.io.IOException {
ServerSocket s = new ServerSocket(5000);
while (true) {
Socket incoming = s.accept();
PrintWriter toClient =
new PrintWriter(incoming.getOutputStream());
toClient.println(new Date());
toClient.flush();
incoming.close();
}
}
}
And following would be As Client:
import java.util.Scanner;
import java.net.Socket;
class DateClient {
public static void main(String[] args) throws java.io.IOException
{
String host = args[0];
int port = Integer.parseInt(args[1]);
Socket server = new Socket(host, port);
Scanner scan = new Scanner( server.getInputStream() );
System.out.println(scan.nextLine());
}
}
You should consider doing this in threads. Right now multiple users can't connect to the server at once. This means that they have to queue for connection to the server resulting in very poor performance.
Normally you receive the client and instantiate a new thread to handle the clients request. I only have exampls in C# so i won't bother you with that, but you can easily find examples on google.
eg.
http://www.kieser.net/linux/java_server.html
I have a class which is a socket client and I am trying to unit test its methods. The tests require that I start a socket server before each test so I use:
#Before
public void setUp() {
if (myServerSocket == null) {
Thread myThread = new Thread() {
public void run() {
DataInputStream dis = null;
DataOutputStream dos = null;
try {
ServerSocket myServer = new ServerSocket(port);
myServerSocket = myServer.accept();
dis = new DataInputStream(myServerSocket.getInputStream());
dos = new DataOutputStream(myServerSocket.getOutputStream());
byte[] bytes = new byte[10];
dis.read(bytes);
boolean breakLoop = false;
do {
if (new String(bytes).length() != 0) {
dos.writeBytes(serverMessage + "\n");
dos.flush();
breakLoop = true;
dos.writeBytes("</BroadsoftDocument>" + "\n");
dos.flush();
}
} while (!breakLoop);
}
catch (IOException e) {
e.printStackTrace();
}
}
};
myThread.start();
}
}
After each test I try to close the server socket so I can reopen the server socket for the next test:
#After
public void tearDown() throws IOException, BroadsoftSocketException {
System.out.println("#After");
if (myServerSocket != null) {
myServerSocket.close();
myServerSocket = null;
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// do nothing.
}
}
}
However, I get "java.net.BindException: Address already in use: JVM_Bind" before each test starting with the second test. I realize I am trying to use the same port for each test but shouldn't closing the socket free up the port?
Quite possibly your socket is still in TIME_WAIT state when you attempt to reconnect it. I would recommend mocking such external dependencies, but if you really do find yourself wanting to continue using a real socket then try setting rebind options. In your setup function, instead of ServerSocket myServer = new ServerSocket(port); do :
final ServerSocket myServer = new ServerSocket();
myServer.setReuseAddress(true);
myServer.bind(new java.net.InetSocketAddress(port));
You already close your serversocket in "setUp" and you really should do it in a finally block.
The port may not be freed immediately. You can avoid this by setting the ServerSocket's reuseAdress to true. See setReuseAddress.
And I second SimonC: maybe you are better off avoiding the socket in the first place.
I am using TCP/IP sockets to create a client and server applicaton. Originally I was using regular sockets but now I have decided to use SSL for my connection. I have created a keystore and have tried running my application but it has yet to be successful.
Here is my code for the server
public class ArFileServer {
public static void main(String[] args)
{
boolean listening = true;
ServerSocketFactory serversocketfactory;
ServerSocket serverSocket;
try
{
//serverSocket = new ServerSocket(4445);
serversocketfactory = SSLServerSocketFactory.getDefault();
serverSocket = serversocketfactory.createServerSocket(4445);
String keystore = System.getProperty("javax.net.ssl.trustStore");
System.out.println(keystore);
// infinite loop to continually listen for connection requests made by clients
while (listening)
{
new ClientConnection(serverSocket.accept()).start();
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
}
serverSocket.close();
}
catch (IOException e)
{
System.out.println("Error could not create socket connection to port, check that port is not busy");
}
}
}
and here is the client code:
public class ClientSocket
{
SocketFactory socketfactory = null;
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
// establish a connection to All Care's server application through socket 4444 (adjust localhost to reflect the IP address that the server
// is being run from)
public ClientSocket()
{
try
{
//clientSocket = new Socket("localhost", 4445);
//SocketFactory socketfactory = SSLSocketFactory.getDefault();
clientSocket = socketfactory.createSocket("192.168.1.8", 4445);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String truststore = System.getProperty("javax.net.ssl.trustStore");
System.out.println(truststore);
}
catch (IOException e)
{
System.out.println("Could not connect to All Care Server Application : " + e.getMessage());
}
}
}
I am also using these runtime arguments:
-Djavax.net.ssl.keyStore=C:\Users\Chris\Documents\NetBeansProjects\ArFile\keystore.jks -Djavax.net.ssl.keyStorePassword=password
When I try to print out the truststore it always returns null, what am I doing wrong?
When I try to print out the truststore it always returns null
Because you never set it. All you are doing is printing out the value of a system property. If you didn't set it, it is null.
what am I doing wrong?
Nothing yet, except printing out meaningless information. But much of your code doesn't make sense:
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
serverSocket being non-null (a) is inevitable at this point, and (b) doesn't have anything do with the client socket being established, which is inevitable at this point.
catch (IOException e)
{
System.out.println("Error could not create socket connection to port, check that port is not busy");
}
An IOException at this point could mean many things, but the one thing it doesn't mean is 'cannot create socket connection to port'. It is the client that does the connecting: the server accepts connections. When you catch an exception, always print its message, don't just make up your own.
You need to define both trustStore and keyStore in runtime arguments:
-Djavax.net.ssl.keyStore=xxx.ks
-Djavax.net.ssl.keyStorePassword=yyy
-Djavax.net.ssl.trustStore=xxx.ks
-Djavax.net.ssl.trustStorePassword=yyy
Both can be same file.
trustStore contains public keys of others.
keyStore contains own keys and certificates.