I ran into an issue trying to read from a DataOutputStream with a Scanner. The following code fails with an input mismatch exception.
DataOutputStream o = new DataOutputStream(new FileOutputStream("temp"));
o.writeByte(1);
o.flush(); o.close();
Scanner i = new Scanner(new FileInputStream("temp"));
System.out.println(i.nextByte());
i.close();
So what output streams ARE compatible with Scanner? And is there an Output/Input stream pair that are built for reading and writing all the primitive types and string lines? I really wanted a non-deprecated readLine() method, and all the input streams I've seen that have that method are deprecated.
EDIT:
The input and output streams will be across sockets for a Client/Server application. Here is the entire relevant code for each side:
SERVER
package server;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;
/**
* Server class handles all clients that wish to read a file stored on this
* server's
* database. Also connects to other servers to share some information.
*
* #author Josh Wilkins
*/
public class Server{
//Server message type constants
private static final byte REPLY = 0;
private static final byte YES = 1;
private static final byte NO = 2;
private static final byte UPDATE = 3;
private final int id;
private final ServerSocket fileServer; //connection point for clients
private HashMap<String, FileObject> files; //list of files in database, hashed by file name
/**
* Creates a new file server with given id on the specified port.
* <p>
* #param id
* #param port
* <p>
* #throws IOException
*/
public Server(int id, int port) throws IOException{
this.id = id;
fileServer = new ServerSocket(port);
files = new HashMap<>();
}
/**
* Loops forever, accepting new clients and creating threads to handle
* them.
* <p>
* #throws IOException
*/
public void acceptClients() throws IOException{
while( true ){
Socket client = fileServer.accept();
(new ClientHandler(client)).run();
}
}
/**
* Sends most updated version of specified file to specified server. Will
* only send update if the server should host the file. UNIMPLEMENTED.
* <p>
* #throws UnsupportedOperationException
*/
private void sendUpdate(int server, FileObject file){
//TODO
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* Creates a new file in the database with the file name contained in the
* string file.
* <p>
* #param file the file name of the new file object
*/
private synchronized void createFileObject(String file){
//TODO: Reject files not hashed to this server
try{
files.put(file, new FileObject(file));
} catch(IOException ex){
System.err.println("Failed to create file: " + file);
ex.printStackTrace(System.err);
}
}
/**
* Determines if this server is allowed to initiate a write request for a
* file by giving the client the most current version number.
* <p>
* #param file the file name of the file in question
* <p>
* #return true if allowed to initiate, false otherwise
*/
private boolean canInitiate(String file){
int hash0 = file.hashCode() % 7;
int hash1 = (file.hashCode() + 1) % 7;
return id == hash0 || id == hash1;
}
/**
* Threaded class to handle all requests from a single client connection.
*/
class ClientHandler extends Thread{
//Client message type constants
private static final byte READ = 0;
private static final byte WRITE = 1;
private static final byte COMMIT = 2;
private static final byte ABORT = 3;
private Socket client;
private DataOutputStream out;
private Scanner in;
private HashMap<String, Integer> pendingUpdates;
/**
* Sets up data input and output streams from given client socket.
* <p>
* #param client the socket that this client is connected to
*/
public ClientHandler(Socket client) throws IOException{
this.client = client;
out = new DataOutputStream(client.getOutputStream());
in = new Scanner(client.getInputStream());
pendingUpdates = new HashMap<>();
}
/**
* Listens for messages coming from client until the connection is
* closed on the client side.
*/
#Override
public void run(){
//Loops until the client closes the connection, then hasNext returns false
while( in.hasNext() ){
//wait for the next message type to be written to the stream
byte msgType = in.nextByte();
switch( msgType ){
case READ:
parseRead();
break;
case WRITE:
parseWrite();
break;
case COMMIT:
parseCommit();
break;
case ABORT:
parseAbort();
break;
default:
}
}
//connection is no longer needed, try to clean everything up
try{
in.close();
out.close();
client.close();
} catch(IOException ex){
System.err.println("Failed to close client at " + client.getInetAddress());
ex.printStackTrace(System.err);
}
}
/**
* Parses read message from client by collecting data from the input
* stream and processing it. Assumes the message type byte has already
* been read. If the file exists in the database, its contents are
* written to the client, otherwise a null string is written.
*/
private void parseRead(){
//TODO: Reject files not hashed to this server
String file = in.nextLine().trim(); //get requested file name (should end with \n)
String contents = "";
if( files.containsKey(file) ){
try{
contents = files.get(file).getContents();
} catch(IOException ex){
System.err.println("Error reading from file: " + file);
ex.printStackTrace(System.err);
}
} else {
//TODO: Need to decide how to handle no such file
// - create file and return empty
// - just return empty, but don't create
// - return some error indicator (change file to "-1" or "File Not Found")
contents = "";
}
//send REPLY message to client
sendReply(file, contents);
}
/**
* Parses write message from client by collecting data form the input
* stream and processing it. Assumes the message type byte has already
* been read. If the file does not exist, one is created immediately
* regardless of further success. If the version number is viable, or
* if this server can initiate a write for the given file, the update is
* queued with the respective FileObject. The client is sent a YES or
* NO answer depending on success of queueing the update.
*/
private void parseWrite(){
//TODO: Reject files not hashed to this server
int version = in.nextInt(); //get version first
String file = in.nextLine().trim(); //get file name
String contents = in.useDelimiter("\\Z").next(); //read entire remaining stream for contents
boolean queued = false;
//Create file if it does not exist yet.
if( !files.containsKey(file) ){
createFileObject(file);
}
//queue update to file object
try{
//only queue if version is given or if this server can initiate
if( version > 0 ){
queued = files.get(file).queueUpdate(contents, version);
} else if( version < 0 && canInitiate(file) ){
queued = files.get(file).queueUpdate(contents);
version = files.get(file).getVersion() + 1;
}
} catch(IOException ex){
System.err.println("Failed to queue update to: " + file);
ex.printStackTrace(System.err);
}
//send response to client (positive if queued, negative if not)
if( queued ){
//TODO: What happens if an update is already queued?
pendingUpdates.put(file, version);
sendYes(version, file);
} else {
sendNo(file);
}
}
/**
* Parses commit message from client by collecting data form the input
* stream and processing it. Assumes the message type byte has already
* been read. If valid server id is read from the stream, an update
* message is sent to that server for the file. No response is sent to
* client.
*/
private void parseCommit(){
//TODO: Reject files not hashed to this server
int failed = in.nextInt();
String file = in.nextLine().trim();
//TODO: Handle improper commit (no pending update)
int version = pendingUpdates.remove(file);
try{
files.get(file).commitUpdate(version);
} catch(IOException ex){
System.err.println("Failed to commit: " + file + " v. " + version);
ex.printStackTrace(System.err);
}
if( failed >= 0 ){
sendUpdate(failed, files.get(file));
}
}
/**
* Parses abort message from client by collecting data form the input
* stream and processing it. Assumes the message type byte has already
* been read. Simply removes the pending update from the queues. No
* response is sent to the client.
*/
private void parseAbort(){
//TODO: Reject files not hashed to this server
String file = in.nextLine().trim();
int version = pendingUpdates.remove(file); //if no update is queued this simply returns null
//what happens if:
// Integer xObj = null;
// int x = xObj;
// print(x);
try{
files.get(file).abortUpdate(version);
} catch(IOException ex){
System.err.println("Failed to abort: " + file + " v. " + version);
ex.printStackTrace(System.err);
}
}
/**
* Sends reply message to client. Assumes partial failure is impossible.
* <p>
* #param file name of file
* #param contents data contained in file
*/
public void sendReply(String file, String contents){
try{
out.writeByte(REPLY);
out.writeChars(file + "\n"); //end file name with CR for easy reading
out.writeChars(contents);
} catch(IOException ex){
System.err.println("Error sending REPLY(" + file + ", <" + contents.length() + ">)");
ex.printStackTrace(System.err);
}
}
/**
* Sends yes message to client. Assumes partial failure is impossible.
* <p>
* #param version this updates version number
* #param file name of file
*/
public void sendYes(int version, String file){
try{
out.writeByte(YES);
out.writeInt(version);
out.writeChars(file + "\n");
} catch(IOException ex){
System.err.println("Error sending YES(" + version + ", " + file + ")");
ex.printStackTrace(System.err);
}
}
/**
* Sends reply message to client. Assumes partial failure is impossible.
* <p>
* #param file name of file
*/
public void sendNo(String file){
try{
out.writeByte(NO);
out.writeChars(file + "\n");
} catch(IOException ex){
System.err.println("Error sending NO(" + file + ")");
ex.printStackTrace(System.err);
}
}
}
}
CLIENT
import java.io.*;
import java.net.Socket;
import java.util.Random;
import java.util.Scanner;
/**
* Client will take as input the operations (WRITE or READ), the file it wishes to use,
* and the servers in the network. The client will attempted to connect to three servers
* when a WRITE is chosen and a random server for READ. The servers ranges for READ and WRITE
* are based on a hashed value of the file name + the next in the line.
* example: Sever 1 , Server 2 and Server 3;
*
* #author kattex
*/
public class Client {
private Socket socket = null;
private Scanner inputStream = null;
private DataOutputStream outputStream = null;
private boolean isConnected = false;
private int sequenceNumber = -1;
private int response = 0;
private byte READ = 0;
private byte WRITE = 1;
private byte COMMIT = 2;
private byte ABORT = 3;
private byte YES = 1;
private byte NO = 2;
private byte REPLY = 0;
/**
* Connect with server code running in local host or in any other host
*/
private void connect(String address, int port) {
try {
// socket = new Socket("localHost", 4445);
System.out.println(address + " " + port);
socket = new Socket(address, port);
//outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new Scanner(socket.getInputStream());
isConnected = true;
} catch (IOException e) {
System.out.println("Unable to connect to server " + address);
}
}
/*
* Create a random integer within a min and max range
*/
public static int randInt(int min, int max, int count) {
Random rand = new Random();
System.out.println("randInt: " + min + "," + max + "," + count);
int randomNum = rand.nextInt((max - min) + 1) + min;
if (randomNum > count){
randomNum = randomNum % count;
if (randomNum < 0){
randomNum += count;
}
}
System.out.println("Random value: " + randomNum);
return randomNum;
}
/*
* Generate hash value for server numbers
*/
public static int hashFileName(String fileName, int serverCount){
int number = fileName.hashCode() % serverCount;
if (number < 0){
number += serverCount;
}
System.out.println("Hash Number: " + number);
return number;
}
/*
* Write out the contents to a file, if the file does not exist create it
*/
public static void CreateFile(String filename, String content){
try {
File file = new File(filename);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
System.out.println("Done");
} catch (IOException e) {
System.out.println("Erro creating file");
e.printStackTrace();
}
}
/*
* Find the next server in the list
*/
public static int nextServer(int number, int count){
int nextInt;
number++;
nextInt = number % count;
if (number < 0){
number += count;
}
return nextInt;
}
/*
* Send the WRITE messaget to server
*/
private void sendWrite(String obj){
try {
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
outputStream.writeByte(WRITE);
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
outputStream.writeInt(sequenceNumber);
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
outputStream.writeChars(obj);
outputStream.writeChar('\n');
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
String contents = readFile(obj);
System.out.println("Contents of file " + obj);
outputStream.writeChars(contents);
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
System.out.println("sending message to server");
int msgType = inputStream.nextByte();
if (msgType == YES){
sequenceNumber = inputStream.nextInt();
String tempFileName = inputStream.nextLine().trim();
response = 1;
System.out.println("Receved YES for file " + tempFileName);
}
if (msgType == NO){
String tempFileName = inputStream.nextLine();
System.out.println("Receved NO for file " + tempFileName);
}
} catch (IOException e) {
System.out.println("Error writing WRITE message to server");
e.printStackTrace(System.err);
}
}
/*
* Read the file into a string that can be sent throught a TCP socket
*/
public String readFile(String fileName) throws FileNotFoundException{
String output = new Scanner(new File(fileName)).useDelimiter("\\Z").next();
System.out.println("File output in READFile" + output);
return output;
}
/*
* Send Abort message to the server
*/
public void sendAbort(String obj){
try {
outputStream.writeByte(ABORT);
outputStream.writeChars(obj);
outputStream.writeChar('\n');
System.out.println("sending abort message to server");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error sending ABORT message to server");
}
}
/*
* Send commit to Server
*/
public void sendCommit(int Fsvr, String obj){
try {
outputStream.writeByte(COMMIT);
outputStream.writeInt(Fsvr);
outputStream.writeBytes(obj);
System.out.println("sending Commit message to server");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error sending COMMIT message to server");
}
}
/*
* Send READ request
*/
public void sendREAD(String obj){
String u;
try {
outputStream.writeByte(READ);
outputStream.writeChars(obj);
outputStream.writeChar('n');
System.out.println("sending READ Request message to server");
byte type = inputStream.nextByte();
//File fl = new File(obj);
if (type == REPLY){
String file = inputStream.nextLine().trim();
String contents = inputStream.useDelimiter("\\z").next();
CreateFile(file, contents);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("Erorro sedning READ Request message to server");
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Client client = new Client();
int serverCount = 0;
int FSvr = -1;
int length = args.length;
String Object = "j.txt";
String type = "write";
int hashValue = hashFileName(Object, 7);
if (type.equals("write") ){
Client client2 = new Client();
Client client3 = new Client();
client.connect("localhost", 4445);
if (client.isConnected){
client.sendWrite(Object);
if (client.response == 1){
client2.sequenceNumber = client.sequenceNumber;
}
}
int nextValue = nextServer(hashValue,7);
//need to add commit message
int thirdValue = 3;
System.out.println("Server Numbers " + hashValue + " " + nextValue + " " + thirdValue);
serverCount = client.response + client2.response + client3.response;
System.out.println("Servercount " + serverCount);
if (serverCount >= 2){
if(client.response != 1 ){FSvr = hashValue; }
if(client2.response != 1){FSvr = nextValue; }
if(client3.response != 1){FSvr = thridValue;}
if(client.response == 1){client.sendCommit( FSvr,Object);}
if(client2.response == 1){client2.sendCommit(FSvr,Object);}
if(client3.response == 1){client3.sendCommit(FSvr,Object);}
}else{
if(client.response == 1 ){client.sendAbort(Object); }
if(client2.response == 1){client2.sendAbort(Object);}
if(client3.response == 1){client3.sendAbort(Object);}
}
} else {
if (type.equals("read")){
int RValue = randInt(hashValue, hashValue + 2, 7);
System.out.println("HashVlue: " + hashValue + " RValue: " + RValue);
client.sendREAD(Object);
}
}
}
}
Most of the message handling on the server side is in ClientHandler. I'm less familiar with the client side, as I didn't write it. Obviously with this implementation, there is an InputMismatchException when reading the byte msgType on the server side. I also realized while searching for the solution, that at the very least I should be adding white space between all the fields for Scanner to parse them separately, but I still have issues.
Use a DataOutputStream and a DataInputStream. Instead of lines, use writeUTF() and readUTF(). For efficiency, put buffered streams underneath, and flush the output before you read.
Scanner takes Input Streams such as System.in you are better off using BufferedReader here. E.g
BufferedReader reader = new BufferReader(new FileReader("temp"));
System.out.println(reader.readLine());
reader.close();
Related
I'm having an issue with my checksum calculated with the CRC32 library in Java.
So the client computes the checksum like so....
/**
* Increments current packet message number, selects a
* random destination, and sends the packet.
* #param connection
* #throws InterruptedException
* #throws IOException
*/
private void generateAndSendPackets(Socket connection) throws InterruptedException, IOException
{
byte packet[] = new byte[5];
for (byte messageNumber = 0; messageNumber <= 20; messageNumber++)
{
packet[0] = CLIENT_ID; //SOURCE
packet[1] = randomDestination(); //DESTINATION
packet[3] = messageNumber; //DATA
packet[4] = messageNumber;
//Need more data?
packet[2] = computeCheckSum(packet); //COMPUTE CHECKSUM
send(packet); //SEND PACKET
Thread.sleep(4000); //WAIT TO SEND NEXT PACKET
}
closeConnection(connection); //Closes the connection
}
/**
* Given a packet, it computes the checksum for
* the packet with internal Checksum library
* #param packet
* #return
*/
private byte computeCheckSum(byte[] packet)
{
Checksum checkSum = new CRC32();
checkSum.update(packet, 0, packet.length);
return (byte)checkSum.getValue();
}
Then sends the packet. Including the checksum.
The Router then calculates the checksum like so...
/**
* Given a packet, it computes the checksum for
* the packet with internal Checksum library
* #param p
* #return
*/
private boolean checkCheckSum(byte[] p)
{
byte[] packet = p;
byte[] tempPacket = new byte[5];
tempPacket[0] = packet[0];
tempPacket[1] = packet[1];
tempPacket[3] = packet[3];
tempPacket[4] = packet[4];
Checksum checkSum = new CRC32();
checkSum.update(tempPacket, 0, tempPacket.length);
byte cc = (byte)checkSum.getValue();
System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + " " + packet[4]);
tempPacket[2] = (byte)checkSum.getValue();
System.out.println(tempPacket[0] + " " + tempPacket[1] + " " + tempPacket[2] + " " + tempPacket[3] + " " + tempPacket[4]);
if((byte)checkSum.getValue() == packet[2]){
System.out.println(packet[2] + "," + cc);
return true;
}else{
System.out.println(packet[2] + "," + cc);
return false;
}
}
So when it computes and outputs, it does it correct the first time...but then after that it just fails like so..
Waiting for connection....
Connection recieved from /127.0.0.1 on port 9000
Waiting for packet...
Packet recieved: 11 44 -118 00
11 44 -118 0 0
11 44 -118 0 0
-118,-118
<Error here because we weren't done another part yet>
Waiting for packet...
Packet recieved: 11 33 -42 11
11 33 -42 1 1
11 33 -128 1 1
-42,-128
Checksum invalid!!!!
Waiting for packet...
Then each after that is invalid....
SO it is getting the checksum correctly once, then screwing up after that to get the checksum again. I think it is something I'm doing wrong with the CRC32 library in Java is my guess. These are all also their own threads, but I don't think that would be an issue.
Here is our code below, I tried to highlight the issue parts above, as there are some parts halfway done with this....
Client.java
package runner;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
/**
* Client side for our client
* server project. Sends a request
* with a string to reverse.
* #author xxxxx
*
*/
public class Client
{
private static final int PORT = 9000;
private static final String HOST = "localhost";
private static final byte CLIENT_ID = (byte)11;
private Random rand;
//For reciving packets
private ServerSocket clientRecieverSocket = null;
//Output to server
private PrintWriter out;
//Input from server
private Scanner conIn;
//Input from user
private Scanner in;
//Data Output Stream
private DataOutputStream dos;
/**
* Creates a new instance of the client
* #param args
* #throws UnknownHostException
* #throws IOException
* #throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException
{
Client c = new Client();
c.run();
}
/**
* Runs the client
*
* #throws UnknownHostException
* #throws IOException
* #throws InterruptedException
*/
private void run() throws IOException, InterruptedException
{
String msg; //Recieve messages from server
//Opens connection
Socket connection = openConnection();
//Gets I/O streams from server
System.out.println("Getting output stream...");
out = new PrintWriter(connection.getOutputStream());
System.out.println("Getting input stream...");
conIn = new Scanner(connection.getInputStream());
System.out.println();
dos = new DataOutputStream(connection.getOutputStream());
msg = conIn.nextLine();
System.out.println(msg);
in = new Scanner(System.in);
generateAndSendPackets(connection);
}
/**
* Increments current packet message number, selects a
* random destination, and sends the packet.
* #param connection
* #throws InterruptedException
* #throws IOException
*/
private void generateAndSendPackets(Socket connection) throws InterruptedException, IOException
{
byte packet[] = new byte[5];
for (byte messageNumber = 0; messageNumber <= 20; messageNumber++)
{
packet[0] = CLIENT_ID; //SOURCE
packet[1] = randomDestination(); //DESTINATION
packet[3] = messageNumber; //DATA
packet[4] = messageNumber;
//Need more data?
packet[2] = computeCheckSum(packet); //COMPUTE CHECKSUM
send(packet); //SEND PACKET
Thread.sleep(4000); //WAIT TO SEND NEXT PACKET
}
closeConnection(connection); //Closes the connection
}
/**
* Given a packet, it computes the checksum for
* the packet with internal Checksum library
* #param packet
* #return
*/
private byte computeCheckSum(byte[] packet)
{
Checksum checkSum = new CRC32();
checkSum.update(packet, 0, packet.length);
return (byte)checkSum.getValue();
}
/**
* Select random destination
* to send to.
*/
private byte randomDestination()
{
List<Byte> destinations = Arrays.asList((byte)22,(byte)33,(byte)44);
//destinations.remove(CLIENT_ID); //Do not send it to itself...
rand = new Random();
return destinations.get(rand.nextInt(destinations.size())); //converts string to byte
}
/**
* Open the connection
* #return
* #throws UnknownHostException
* #throws IOException
*/
private Socket openConnection() throws IOException
{
System.out.println("Connecting to server...");
Socket connection = new Socket(HOST, PORT); //Connects to server
System.out.println("Connection made!");
return connection;
}
/**
* Closes the connection
* #param connection
* #throws IOException
*/
private void closeConnection(Socket connection) throws IOException
{
System.out.println("Closing connection...");
connection.close();
}
/**
* Sends a message to the server
* with the string to reverse.
* #param packet
*/
private void send(byte[] packet) throws IOException
{
System.out.println("You sent " + packet + ", sending message...");
System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + " " + packet[4]);
dos.write(packet, 0, packet.length);
dos.flush();
}
}
Router.java
import javax.xml.crypto.Data;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
/**
* Router class routes messages
* around to different routers/clients
*
* #Author Abe and Carson
*/
public class Router{
//Stores routing table
private Hashtable<Byte, String> routingTable;
//Stores socket
private static ServerSocket SERVER;
private static Socket CLIENT;
//Stores router ID (CHANGE THIS IS HARDCODED!!!!!!)
private static final int ROUTER_ID = 1;
public static void main(String args[]) throws IOException
{
Router r = new Router();
System.out.println("Waiting for connection....");
while(true)
{
Socket incomingConnection = SERVER.accept();
System.out.println("Connection recieved from "
+ incomingConnection.getInetAddress()
+ " on port "
+ incomingConnection.getLocalPort());
RouterHandlerThread rht = new RouterHandlerThread(incomingConnection, r);
rht.start();
}
}
/**
* Creates a router object
* with a server socket that opens to listen for packets
* and a routing table
*/
public Router()
{
//Creates routing tables HashTable<Byte, String> for router to use based on its ID
RoutingTableFactory rtf = new RoutingTableFactory();
try{
routingTable = rtf.getRoutingTable(ROUTER_ID);
} catch(RoutingTableFactory.InvalidRouterIDException e){
e.printStackTrace();
}
try {
SERVER = new ServerSocket(9000);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Getter for the routers
* Routing Table
* #return
*/
public Hashtable<Byte, String> getRoutingTable()
{
return this.routingTable;
}
/**
* Thread for handling router processes for
* forwarding a packet to a different link.
*/
private static class RouterHandlerThread extends Thread
{
private Socket connection;
private Router router;
private Scanner in;
private PrintWriter out;
//Used for sending the packet byte[], can't use Scanner for byte[] :(
private DataInputStream dis;
RouterHandlerThread(Socket c, Router r) throws IOException
{
this.router = r;
this.connection = c;
in = new Scanner(c.getInputStream());
out = new PrintWriter(c.getOutputStream());
dis = new DataInputStream(c.getInputStream());
}
/**
* Given a packet, it computes the checksum for
* the packet with internal Checksum library
* #param p
* #return
*/
private boolean checkCheckSum(byte[] p)
{
byte[] packet = p;
byte[] tempPacket = new byte[5];
tempPacket[0] = packet[0];
tempPacket[1] = packet[1];
tempPacket[3] = packet[3];
tempPacket[4] = packet[4];
Checksum checkSum = new CRC32();
checkSum.update(tempPacket, 0, tempPacket.length);
byte cc = (byte)checkSum.getValue();
System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + " " + packet[4]);
tempPacket[2] = (byte)checkSum.getValue();
System.out.println(tempPacket[0] + " " + tempPacket[1] + " " + tempPacket[2] + " " + tempPacket[3] + " " + tempPacket[4]);
if((byte)checkSum.getValue() == packet[2]){
System.out.println(packet[2] + "," + cc);
return true;
}else{
System.out.println(packet[2] + "," + cc);
return false;
}
}
public void run()
{
out.println("R: Connected to router " + ROUTER_ID + " at " + SERVER.getLocalPort());
out.flush();
while(connection.isConnected())
{
byte[] packet = new byte[5];
System.out.println("Waiting for packet...");
//Reads packet byte[] from the client, stores in packet.
try{
dis.readFully(packet);
}catch(Exception e){
e.printStackTrace();
}
//Print out each byte of packet.
System.out.println("Packet recieved: " + packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + packet[4]);
//Get routing table, look up what link to send packet to.
Hashtable<Byte, String> routingTable = router.getRoutingTable();
if(checkCheckSum(packet)){
String destination = routingTable.get(packet[1]);
try {
Socket targetRouter = new Socket(destination, 9000);
DataOutputStream dos = new DataOutputStream(targetRouter.getOutputStream());
dos.write(packet);
dos.flush();
System.out.println("Forwarding to " + destination);
targetRouter.close();
dos.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else{
System.out.println("Checksum invalid!!!!");
}
}
}
}
}
/**********
* CODE FIDDLING WITH STRINGS -> BYTES AND VICE VERSA
public static void main(String[] args)
{
byte packet[] = new byte[4];
packet[0] = 'D';
packet[1] = 'B';
packet[3] = 29;
Checksum checkSum = new CRC32();
checkSum.update(packet, 0, packet.length);
packet[2] = (byte)checkSum.getValue();
System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3]);
String str = new String(packet);
System.out.println(str);
}
*/
When you compute the checksum, packet[2] must be set to zero. In some part of your code, namely inside the function generateAndSendPackets, you are reusing the same byte[] to send multiple packets, but you are keeping the previous checksum byte in packet[2], resulting in an incorrect new checksum value.
byte packet[] = new byte[5];
for (byte messageNumber = 0; messageNumber <= 20; messageNumber++)
{
packet[0] = CLIENT_ID; //SOURCE
packet[1] = randomDestination(); //DESTINATION
packet[3] = messageNumber; //DATA
packet[4] = messageNumber;
//Need more data?
// ********************
packet[2] = (byte) 0; // <<<<<< You have to set it to zero
// ********************
packet[2] = computeCheckSum(packet); //COMPUTE CHECKSUM
send(packet); //SEND PACKET
Thread.sleep(4000); //WAIT TO SEND NEXT PACKET
}
We are trying to connect FX9500 using LLRP tool kit code. We would like to receive read tag as soon as they come into range. From messages it looks like all add/set config are done properly, but can't receive events.
Attached are code and XML output of messages being exchanged.
XML Messages are at : http://gadgetnapps.blogspot.in/2016/02/llrp-xml-messages.html
Thanks in advance.
public class LLRPHelloWorld {
private static String ipAddress = null;
private static int readerPort = -1;
private Socket connection;
private DataOutputStream out;
private static int ROSPEC_ID = 999;
private static Logger logger;
private ReadThread rt = null;
static AppCtx ctxMain;
public static void rfidMain(String ipAdString, int port, AppCtx ctx) {
logger = Logger.getLogger(LLRPHelloWorld.class);
ipAddress = ipAdString;
readerPort = port;
ctxMain = ctx;
try {
new LLRPHelloWorld();
logger.info("LLRP Hello World has terminated");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* The constructor creates a connection to the reader and sends LLRP
* messages. It first sends a GET_READER_CAPABILIITIES message and a
* SET_READER_CONFIG message. Then it creates an ROSpec with null start and
* stop triggers. After it enables and starts the ROSpec. It waits for a few
* seconds to receive tag reads before it disables and deletes the ROSpec.
* Finally it ends the LLRP connection.
*
* #param ctx
*
* #throws IOException
*/
public LLRPHelloWorld() throws IOException {
// Try to establish a connection to the reader
connection = new Socket(ipAddress, readerPort);
out = new DataOutputStream(connection.getOutputStream());
// Start up the ReaderThread to read messages form socket to Console
rt = new ReadThread(connection);
rt.start();
// Wait for the NotificationEvent the Reader sends whenever a
// connection attempt is made
pause(250);
LLRPMessage m = rt.getNextMessage();
READER_EVENT_NOTIFICATION readerEventNotification = (READER_EVENT_NOTIFICATION) m;
ReaderEventNotificationData red = readerEventNotification
.getReaderEventNotificationData();
if (red.getConnectionAttemptEvent() != null) {
logger.info("Connection attempt was successful");
} else {
logger.error("Connection attempt was unsucessful");
System.exit(-1);
}
// Create a GET_READER_CAPABILITIES Message and send it to the reader
GET_READER_CAPABILITIES getReaderCap = new GET_READER_CAPABILITIES();
getReaderCap.setRequestedData(new GetReaderCapabilitiesRequestedData(
GetReaderCapabilitiesRequestedData.All));
write(getReaderCap, "GET_READER_CAPABILITIES");
pause(250);
// Create a SET_READER_CONFIG Message and send it to the reader
SET_READER_CONFIG setReaderConfig = createSetReaderConfig();
write(setReaderConfig, "SET_READER_CONFIG");
pause(250);
// CREATE an ADD_ROSPEC Message and send it to the reader
ADD_ROSPEC addROSpec = new ADD_ROSPEC();
addROSpec.setROSpec(createROSpec());
write(addROSpec, "ADD_ROSPEC");
pause(250);
// Create an ENABLE_ROSPEC message and send it to the reader
ENABLE_ROSPEC enableROSpec = new ENABLE_ROSPEC();
enableROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
write(enableROSpec, "ENABLE_ROSPEC");
pause(250);
boolean flg = true;
START_ROSPEC startROSpec = new START_ROSPEC();
startROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
write(startROSpec, "START_ROSPEC");
while (flg) {
// Create a START_ROSPEC message and send it to the reader
LLRPMessage msg = rt.getNextMessage();
try {
System.err.println(msg+"--->"+msg.toXMLString());
} catch (InvalidLLRPMessageException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// pause(4000);
// System.err.println("main test 4s");
// Create a STOP_ROSPEC message and send it to the reader
// STOP_ROSPEC stopROSpec = new STOP_ROSPEC();
// stopROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
// write(stopROSpec, "STOP_ROSPEC");
//
// pause(4000);
// startROSpec = new START_ROSPEC();
// startROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
// write(startROSpec, "START_ROSPEC");
//
}
// Create a DISABLE_ROSPEC message and send it to the reader
DISABLE_ROSPEC disableROSpec = new DISABLE_ROSPEC();
disableROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
write(disableROSpec, "DISABLE_ROSPEC");
pause(250);
// Create a DELTE_ROSPEC message and send it to the reader
DELETE_ROSPEC deleteROSpec = new DELETE_ROSPEC();
deleteROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
write(deleteROSpec, "DELETE_ROSPEC");
pause(250);
// wait for one second before closing the connection
pause(1000);
// Create a CLOSE_CONNECTION message and send it to the reader
CLOSE_CONNECTION cc = new CLOSE_CONNECTION();
write(cc, "CloseConnection");
synchronized (rt) {
try {
logger.debug("Wait for the Reader to close the Connection");
rt.wait();
// KEEPALIVE_ACK
} catch (InterruptedException e) {
// Quit the Program
}
}
}
/**
* This method creates a ROSpec with null start and stop triggers
*
* #return
*/
private ROSpec createROSpec() {
// create a new rospec
ROSpec roSpec = new ROSpec();
roSpec.setPriority(new UnsignedByte(0));
roSpec.setCurrentState(new ROSpecState(ROSpecState.Disabled));//rathi
roSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
// set up ROBoundary (start and stop triggers)
ROBoundarySpec roBoundarySpec = new ROBoundarySpec();
ROSpecStartTrigger startTrig = new ROSpecStartTrigger();
startTrig.setROSpecStartTriggerType(new ROSpecStartTriggerType(
ROSpecStartTriggerType.Immediate));
// PeriodicTriggerValue pt =new PeriodicTriggerValue();
// pt.setPeriod(new UnsignedInteger(1));
// pt.setOffset(new UnsignedInteger(0));
// startTrig.setPeriodicTriggerValue(pt);
roBoundarySpec.setROSpecStartTrigger(startTrig);
ROSpecStopTrigger stopTrig = new ROSpecStopTrigger();
stopTrig.setDurationTriggerValue(new UnsignedInteger(0));
stopTrig.setROSpecStopTriggerType(new ROSpecStopTriggerType(
ROSpecStopTriggerType.Null));
roBoundarySpec.setROSpecStopTrigger(stopTrig);
roSpec.setROBoundarySpec(roBoundarySpec);
// Add an AISpec
AISpec aispec = new AISpec();
// set AI Stop trigger to null
AISpecStopTrigger aiStopTrigger = new AISpecStopTrigger();
aiStopTrigger.setAISpecStopTriggerType(new AISpecStopTriggerType(
AISpecStopTriggerType.Null));//null
aiStopTrigger.setDurationTrigger(new UnsignedInteger(0));
aispec.setAISpecStopTrigger(aiStopTrigger);
UnsignedShortArray antennaIDs = new UnsignedShortArray();
antennaIDs.add(new UnsignedShort(0));
aispec.setAntennaIDs(antennaIDs);
InventoryParameterSpec inventoryParam = new InventoryParameterSpec();
inventoryParam.setProtocolID(new AirProtocols(
AirProtocols.EPCGlobalClass1Gen2));
inventoryParam.setInventoryParameterSpecID(new UnsignedShort(1));
aispec.addToInventoryParameterSpecList(inventoryParam);
roSpec.addToSpecParameterList(aispec);
return roSpec;
}
/**
* This method creates a SET_READER_CONFIG method
*
* #return
*/
private SET_READER_CONFIG createSetReaderConfig() {
SET_READER_CONFIG setReaderConfig = new SET_READER_CONFIG();
// Create a default RoReportSpec so that reports are sent at the end of
// ROSpecs
ROReportSpec roReportSpec = new ROReportSpec();
roReportSpec.setN(new UnsignedShort(0));
roReportSpec.setROReportTrigger(new ROReportTriggerType(
ROReportTriggerType.Upon_N_Tags_Or_End_Of_ROSpec));
//Enable keep alive
// KeepaliveSpec ka = new KeepaliveSpec();
// KeepaliveTriggerType ktype = new KeepaliveTriggerType();
// ktype.set(KeepaliveTriggerType.Periodic);
// ka.setPeriodicTriggerValue(new UnsignedInteger(100));
// ka.setKeepaliveTriggerType(ktype);
// setReaderConfig.setKeepaliveSpec(ka);
//
TagReportContentSelector tagReportContentSelector = new TagReportContentSelector();
tagReportContentSelector.setEnableAccessSpecID(new Bit(0));
tagReportContentSelector.setEnableAntennaID(new Bit(1));
tagReportContentSelector.setEnableChannelIndex(new Bit(0));
tagReportContentSelector.setEnableFirstSeenTimestamp(new Bit(0));
tagReportContentSelector.setEnableInventoryParameterSpecID(new Bit(1));
tagReportContentSelector.setEnableLastSeenTimestamp(new Bit(0));
tagReportContentSelector.setEnablePeakRSSI(new Bit(0));
tagReportContentSelector.setEnableROSpecID(new Bit(1));
tagReportContentSelector.setEnableSpecIndex(new Bit(0));
tagReportContentSelector.setEnableTagSeenCount(new Bit(0));
// tagReport.
C1G2EPCMemorySelector epcMemSel = new C1G2EPCMemorySelector();
epcMemSel.setEnableCRC(new Bit(0));
epcMemSel.setEnablePCBits(new Bit(0));
tagReportContentSelector
.addToAirProtocolEPCMemorySelectorList(epcMemSel);
roReportSpec.setTagReportContentSelector(tagReportContentSelector);
setReaderConfig.setROReportSpec(roReportSpec);
// Set default AccessReportSpec
AccessReportSpec accessReportSpec = new AccessReportSpec();
accessReportSpec.setAccessReportTrigger(new AccessReportTriggerType(
AccessReportTriggerType.End_Of_AccessSpec));
setReaderConfig.setAccessReportSpec(accessReportSpec);
// Set up reporting for AISpec events, ROSpec events, and GPI Events
ReaderEventNotificationSpec eventNoteSpec = new ReaderEventNotificationSpec();
EventNotificationState noteState = new EventNotificationState();
noteState.setEventType(new NotificationEventType(
NotificationEventType.AISpec_Event));
noteState.setNotificationState(new Bit(1));
eventNoteSpec.addToEventNotificationStateList(noteState);
noteState = new EventNotificationState();
noteState.setEventType(new NotificationEventType(
NotificationEventType.ROSpec_Event));
noteState.setNotificationState(new Bit(1));
eventNoteSpec.addToEventNotificationStateList(noteState);
noteState = new EventNotificationState();
noteState.setEventType(new NotificationEventType(
NotificationEventType.GPI_Event));
noteState.setNotificationState(new Bit(1));
eventNoteSpec.addToEventNotificationStateList(noteState);
noteState = new EventNotificationState();
noteState.setEventType(new NotificationEventType(
NotificationEventType.Antenna_Event));
noteState.setNotificationState(new Bit(1));
eventNoteSpec.addToEventNotificationStateList(noteState);
setReaderConfig.setReaderEventNotificationSpec(eventNoteSpec);
setReaderConfig.setResetToFactoryDefault(new Bit(0));
return setReaderConfig;
}
/**
* This method causes the calling thread to sleep for a specified number of
* milliseconds
*
* #param ms
*/
private void pause(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Send a llrp message to the reader
*
* #param msg
* Message to be send
* #param message
* Description for output purposes
*/
private void write(LLRPMessage msg, String message) {
try {
logger.info(" Sending message: \n" + msg.toXMLString());
out.write(msg.encodeBinary());
} catch (IOException e) {
logger.error("Couldn't send Command ", e);
} catch (InvalidLLRPMessageException e) {
logger.error("Couldn't send Command", e);
}
}
/**
*
* This class is a allows LLRP messages to be read on a separate thread
*
* #author Kyle Neumeier
* #author Andreas Huebner
*
*/
class ReadThread extends Thread {
/**
* The incoming data stream from the LLRP reader connection
*/
private DataInputStream inStream = null;
/**
* The socket for the connection to the LLRP Reader
*/
private Socket socket = null;
/**
* A queue to store incoming LLRP Messages
*/
private LinkedBlockingQueue<LLRPMessage> queue = null;
/**
* Thread for constant reading of the stream
*
* #param inStream
*/
public ReadThread(Socket socket) {
this.socket = socket;
this.queue = new LinkedBlockingQueue<LLRPMessage>();
try {
this.inStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
logger.error("Cannot get input stream", e);
}
}
#Override
public void run() {
int i = 0;
super.run();
if (socket.isConnected()) {
while (!socket.isClosed()) {
LLRPMessage message = null;
try {
message = read();
if (message != null) {
queue.put(message);
logger.info("Received Message: \n"
+ message);//.toXMLString());
if (message instanceof org.llrp.ltk.generated.messages.RO_ACCESS_REPORT) {
// logger.info("Received Message: \n"
// + message.toXMLString());
RO_ACCESS_REPORT re = (RO_ACCESS_REPORT) message;
java.util.List<TagReportData> list = re
.getTagReportDataList();
for (TagReportData tagReportData : list) {
if (tagReportData.getEPCParameter() instanceof EPC_96) {
EPC_96 epc = (EPC_96) tagReportData
.getEPCParameter();
System.err
.println("=====================================>>>>>>>>>>>>>>>>>"
+ epc.getEPC());
// sendWebMessage(epc.getEPC(),i++);
}
}
}
} else {
logger.info("closing socket");
socket.close();
}
} catch (IOException e) {
logger.error("Error while reading message", e);
} catch (InvalidLLRPMessageException e) {
logger.error("Error while reading message", e);
} catch (InterruptedException e) {
logger.error("Error while reading message", e);
}
}
}
}
private void sendWebMessage(Integer96_HEX epc, int i)
throws InterruptedException {
WebMessage cmd = new WebMessage();
String url;
if (i % 2 == 0)
url = ctxMain.getWorker().getAddLogUrl() + "/" + epc;
else
url = ctxMain.getWorker().getTransationUrl() + "/" + epc;
cmd.setUrl(url);
System.out.println(" id " + url);
cmd.setMessage(new String("{}"));
ctxMain.sendWebMessage(cmd);
}
/**
* Read everything from the stream until the socket is closed
*
* #throws InvalidLLRPMessageException
*/
public LLRPMessage read() throws IOException,
InvalidLLRPMessageException {
LLRPMessage m = null;
// The message header
byte[] first = new byte[6];
// the complete message
byte[] msg;
// Read in the message header. If -1 is read, there is no more
// data available, so close the socket
if (inStream.read(first, 0, 6) == -1) {
return null;
}
int msgLength = 0;
try {
// calculate message length
msgLength = calculateLLRPMessageLength(first);
} catch (IllegalArgumentException e) {
throw new IOException("Incorrect Message Length");
}
/*
* the rest of bytes of the message will be stored in here before
* they are put in the accumulator. If the message is short, all
* messageLength-6 bytes will be read in here at once. If it is
* long, the data might not be available on the socket all at once,
* so it make take a couple of iterations to read in all the bytes
*/
byte[] temp = new byte[msgLength - 6];
// all the rest of the bytes will be put into the accumulator
ArrayList<Byte> accumulator = new ArrayList<Byte>();
// add the first six bytes to the accumulator so that it will
// contain all the bytes at the end
for (byte b : first) {
accumulator.add(b);
}
// the number of bytes read on the last call to read()
int numBytesRead = 0;
// read from the input stream and put bytes into the accumulator
// while there are still bytes left to read on the socket and
// the entire message has not been read
while (((msgLength - accumulator.size()) != 0)
&& numBytesRead != -1) {
numBytesRead = inStream.read(temp, 0,
msgLength - accumulator.size());
for (int i = 0; i < numBytesRead; i++) {
accumulator.add(temp[i]);
}
}
if ((msgLength - accumulator.size()) != 0) {
throw new IOException("Error: Discrepency between message size"
+ " in header and actual number of bytes read");
}
msg = new byte[msgLength];
// copy all bytes in the accumulator to the msg byte array
for (int i = 0; i < accumulator.size(); i++) {
msg[i] = accumulator.get(i);
}
// turn the byte array into an LLRP Message Object
m = LLRPMessageFactory.createLLRPMessage(msg);
return m;
}
/**
* Send in the first 6 bytes of an LLRP Message
*
* #param bytes
* #return
*/
private int calculateLLRPMessageLength(byte[] bytes)
throws IllegalArgumentException {
long msgLength = 0;
int num1 = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
num1 = ((unsignedByteToInt(bytes[2])));
num1 = num1 << 32;
if (num1 > 127) {
throw new RuntimeException(
"Cannot construct a message greater than "
+ "2147483647 bytes (2^31 - 1), due to the fact that there are "
+ "no unsigned ints in java");
}
num2 = ((unsignedByteToInt(bytes[3])));
num2 = num2 << 16;
num3 = ((unsignedByteToInt(bytes[4])));
num3 = num3 << 8;
num4 = (unsignedByteToInt(bytes[5]));
msgLength = num1 + num2 + num3 + num4;
if (msgLength < 0) {
throw new IllegalArgumentException(
"LLRP message length is less than 0");
} else {
return (int) msgLength;
}
}
/**
* From http://www.rgagnon.com/javadetails/java-0026.html
*
* #param b
* #return
*/
private int unsignedByteToInt(byte b) {
return (int) b & 0xFF;
}
/**
* Receive the next Message
*
* #return returns the Message form the Queue and removes it. It blocks
* if there is no Message.
*/
public LLRPMessage getNextMessage() {
LLRPMessage m = null;
try {
m = queue.take();
} catch (InterruptedException e) {
// nothing
}
return m;
}
}
}
You have to need write report after the startRoSpec then you get tagids.
> START_ROSPEC startROSpec = new START_ROSPEC();
> startROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
> write(startROSpec, "START_ROSPEC"); //wait for five seconds for tag
> reads pause(5000);
ENABLE_EVENTS_AND_REPORTS report = new ENABLE_EVENTS_AND_REPORTS();
write(report, "ENABLE_EVENTS_AND_REPORTS");
You can get class from : https://github.com/kaansey/JAVA-LLRP-RFIDTags
I am writing a java application to serve as a local proxy. I have been helped greatly by this piece of code from http://www.nsftools.com/tips/jProxy.java. See program below:
/* <!-- in case someone opens this in a browser... --> <pre> */
/*
* This is a simple multi-threaded Java proxy server
* for HTTP requests (HTTPS doesn't seem to work, because
* the CONNECT requests aren't always handled properly).
* I implemented the class as a thread so you can call it
* from other programs and kill it, if necessary (by using
* the closeSocket() method).
*
* We'll call this the 1.1 version of this class. All I
* changed was to separate the HTTP header elements with
* \r\n instead of just \n, to comply with the official
* HTTP specification.
*
* This can be used either as a direct proxy to other
* servers, or as a forwarding proxy to another proxy
* server. This makes it useful if you want to monitor
* traffic going to and from a proxy server (for example,
* you can run this on your local machine and set the
* fwdServer and fwdPort to a real proxy server, and then
* tell your browser to use "localhost" as the proxy, and
* you can watch the browser traffic going in and out).
*
* One limitation of this implementation is that it doesn't
* close the ProxyThread socket if the client disconnects
* or the server never responds, so you could end up with
* a bunch of loose threads running amuck and waiting for
* connections. As a band-aid, you can set the server socket
* to timeout after a certain amount of time (use the
* setTimeout() method in the ProxyThread class), although
* this can cause false timeouts if a remote server is simply
* slow to respond.
*
* Another thing is that it doesn't limit the number of
* socket threads it will create, so if you use this on a
* really busy machine that processed a bunch of requests,
* you may have problems. You should use thread pools if
* you're going to try something like this in a "real"
* application.
*
* Note that if you're using the "main" method to run this
* by itself and you don't need the debug output, it will
* run a bit faster if you pipe the std output to 'nul'.
*
* You may use this code as you wish, just don't pretend
* that you wrote it yourself, and don't hold me liable for
* anything that it does or doesn't do. If you're feeling
* especially honest, please include a link to nsftools.com
* along with the code. Thanks, and good luck.
*
* Julian Robichaux -- http://www.nsftools.com
*/
import java.io.*;
import java.net.*;
import java.lang.reflect.Array;
public class jProxy extends Thread
{
public static final int DEFAULT_PORT = 8080;
private ServerSocket server = null;
private int thisPort = DEFAULT_PORT;
private String fwdServer = "";
private int fwdPort = 0;
private int ptTimeout = ProxyThread.DEFAULT_TIMEOUT;
private int debugLevel = 0;
private PrintStream debugOut = System.out;
/* here's a main method, in case you want to run this by itself */
public static void main (String args[])
{
int port = 0;
String fwdProxyServer = "";
int fwdProxyPort = 0;
if (args.length == 0)
{
System.err.println("USAGE: java jProxy <port number> [<fwd proxy> <fwd port>]");
System.err.println(" <port number> the port this service listens on");
System.err.println(" <fwd proxy> optional proxy server to forward requests to");
System.err.println(" <fwd port> the port that the optional proxy server is on");
System.err.println("\nHINT: if you don't want to see all the debug information flying by,");
System.err.println("you can pipe the output to a file or to 'nul' using \">\". For example:");
System.err.println(" to send output to the file prox.txt: java jProxy 8080 > prox.txt");
System.err.println(" to make the output go away: java jProxy 8080 > nul");
return;
}
// get the command-line parameters
port = Integer.parseInt(args[0]);
if (args.length > 2)
{
fwdProxyServer = args[1];
fwdProxyPort = Integer.parseInt(args[2]);
}
// create and start the jProxy thread, using a 20 second timeout
// value to keep the threads from piling up too much
System.err.println(" ** Starting jProxy on port " + port + ". Press CTRL-C to end. **\n");
jProxy jp = new jProxy(port, fwdProxyServer, fwdProxyPort, 20);
jp.setDebug(1, System.out); // or set the debug level to 2 for tons of output
jp.start();
// run forever; if you were calling this class from another
// program and you wanted to stop the jProxy thread at some
// point, you could write a loop that waits for a certain
// condition and then calls jProxy.closeSocket() to kill
// the running jProxy thread
while (true)
{
try { Thread.sleep(3000); } catch (Exception e) {}
}
// if we ever had a condition that stopped the loop above,
// we'd want to do this to kill the running thread
//jp.closeSocket();
//return;
}
/* the proxy server just listens for connections and creates
* a new thread for each connection attempt (the ProxyThread
* class really does all the work)
*/
public jProxy (int port)
{
thisPort = port;
}
public jProxy (int port, String proxyServer, int proxyPort)
{
thisPort = port;
fwdServer = proxyServer;
fwdPort = proxyPort;
}
public jProxy (int port, String proxyServer, int proxyPort, int timeout)
{
thisPort = port;
fwdServer = proxyServer;
fwdPort = proxyPort;
ptTimeout = timeout;
}
/* allow the user to decide whether or not to send debug
* output to the console or some other PrintStream
*/
public void setDebug (int level, PrintStream out)
{
debugLevel = level;
debugOut = out;
}
/* get the port that we're supposed to be listening on
*/
public int getPort ()
{
return thisPort;
}
/* return whether or not the socket is currently open
*/
public boolean isRunning ()
{
if (server == null)
return false;
else
return true;
}
/* closeSocket will close the open ServerSocket; use this
* to halt a running jProxy thread
*/
public void closeSocket ()
{
try {
// close the open server socket
server.close();
// send it a message to make it stop waiting immediately
// (not really necessary)
/*Socket s = new Socket("localhost", thisPort);
OutputStream os = s.getOutputStream();
os.write((byte)0);
os.close();
s.close();*/
} catch(Exception e) {
if (debugLevel > 0)
debugOut.println(e);
}
server = null;
}
public void run()
{
try {
// create a server socket, and loop forever listening for
// client connections
server = new ServerSocket(thisPort);
if (debugLevel > 0)
debugOut.println("Started jProxy on port " + thisPort);
while (true)
{
Socket client = server.accept();
ProxyThread t = new ProxyThread(client, fwdServer, fwdPort);
t.setDebug(debugLevel, debugOut);
t.setTimeout(ptTimeout);
t.start();
}
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("jProxy Thread error: " + e);
}
closeSocket();
}
}
/*
* The ProxyThread will take an HTTP request from the client
* socket and send it to either the server that the client is
* trying to contact, or another proxy server
*/
class ProxyThread extends Thread
{
private Socket pSocket;
private String fwdServer = "";
private int fwdPort = 0;
private int debugLevel = 0;
private PrintStream debugOut = System.out;
// the socketTimeout is used to time out the connection to
// the remote server after a certain period of inactivity;
// the value is in milliseconds -- use zero if you don't want
// a timeout
public static final int DEFAULT_TIMEOUT = 20 * 1000;
private int socketTimeout = DEFAULT_TIMEOUT;
public ProxyThread(Socket s)
{
pSocket = s;
}
public ProxyThread(Socket s, String proxy, int port)
{
pSocket = s;
fwdServer = proxy;
fwdPort = port;
}
public void setTimeout (int timeout)
{
// assume that the user will pass the timeout value
// in seconds (because that's just more intuitive)
socketTimeout = timeout * 1000;
}
public void setDebug (int level, PrintStream out)
{
debugLevel = level;
debugOut = out;
}
public void run()
{
try
{
long startTime = System.currentTimeMillis();
// client streams (make sure you're using streams that use
// byte arrays, so things like GIF and JPEG files and file
// downloads will transfer properly)
BufferedInputStream clientIn = new BufferedInputStream(pSocket.getInputStream());
BufferedOutputStream clientOut = new BufferedOutputStream(pSocket.getOutputStream());
// the socket to the remote server
Socket server = null;
// other variables
byte[] request = null;
byte[] response = null;
int requestLength = 0;
int responseLength = 0;
int pos = -1;
StringBuffer host = new StringBuffer("");
String hostName = "";
int hostPort = 80;
// get the header info (the web browser won't disconnect after
// it's sent a request, so make sure the waitForDisconnect
// parameter is false)
request = getHTTPData(clientIn, host, false);
requestLength = Array.getLength(request);
// separate the host name from the host port, if necessary
// (like if it's "servername:8000")
hostName = host.toString();
pos = hostName.indexOf(":");
if (pos > 0)
{
try { hostPort = Integer.parseInt(hostName.substring(pos + 1));
} catch (Exception e) { }
hostName = hostName.substring(0, pos);
}
// either forward this request to another proxy server or
// send it straight to the Host
try
{
if ((fwdServer.length() > 0) && (fwdPort > 0))
{
server = new Socket(fwdServer, fwdPort);
} else {
server = new Socket(hostName, hostPort);
}
} catch (Exception e) {
// tell the client there was an error
String errMsg = "HTTP/1.0 500\nContent Type: text/plain\n\n" +
"Error connecting to the server:\n" + e + "\n";
clientOut.write(errMsg.getBytes(), 0, errMsg.length());
}
if (server != null)
{
server.setSoTimeout(socketTimeout);
BufferedInputStream serverIn = new BufferedInputStream(server.getInputStream());
BufferedOutputStream serverOut = new BufferedOutputStream(server.getOutputStream());
// send the request out
serverOut.write(request, 0, requestLength);
serverOut.flush();
// and get the response; if we're not at a debug level that
// requires us to return the data in the response, just stream
// it back to the client to save ourselves from having to
// create and destroy an unnecessary byte array. Also, we
// should set the waitForDisconnect parameter to 'true',
// because some servers (like Google) don't always set the
// Content-Length header field, so we have to listen until
// they decide to disconnect (or the connection times out).
if (debugLevel > 1)
{
response = getHTTPData(serverIn, true);
responseLength = Array.getLength(response);
} else {
responseLength = streamHTTPData(serverIn, clientOut, true);
}
serverIn.close();
serverOut.close();
}
// send the response back to the client, if we haven't already
if (debugLevel > 1)
clientOut.write(response, 0, responseLength);
// if the user wants debug info, send them debug info; however,
// keep in mind that because we're using threads, the output won't
// necessarily be synchronous
if (debugLevel > 0)
{
long endTime = System.currentTimeMillis();
debugOut.println("Request from " + pSocket.getInetAddress().getHostAddress() +
" on Port " + pSocket.getLocalPort() +
" to host " + hostName + ":" + hostPort +
"\n (" + requestLength + " bytes sent, " +
responseLength + " bytes returned, " +
Long.toString(endTime - startTime) + " ms elapsed)");
debugOut.flush();
}
if (debugLevel > 1)
{
debugOut.println("REQUEST:\n" + (new String(request)));
debugOut.println("RESPONSE:\n" + (new String(response)));
debugOut.flush();
}
// close all the client streams so we can listen again
clientOut.close();
clientIn.close();
pSocket.close();
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error in ProxyThread: " + e);
//e.printStackTrace();
}
}
private byte[] getHTTPData (InputStream in, boolean waitForDisconnect)
{
// get the HTTP data from an InputStream, and return it as
// a byte array
// the waitForDisconnect parameter tells us what to do in case
// the HTTP header doesn't specify the Content-Length of the
// transmission
StringBuffer foo = new StringBuffer("");
return getHTTPData(in, foo, waitForDisconnect);
}
private byte[] getHTTPData (InputStream in, StringBuffer host, boolean waitForDisconnect)
{
// get the HTTP data from an InputStream, and return it as
// a byte array, and also return the Host entry in the header,
// if it's specified -- note that we have to use a StringBuffer
// for the 'host' variable, because a String won't return any
// information when it's used as a parameter like that
ByteArrayOutputStream bs = new ByteArrayOutputStream();
streamHTTPData(in, bs, host, waitForDisconnect);
return bs.toByteArray();
}
private int streamHTTPData (InputStream in, OutputStream out, boolean waitForDisconnect)
{
StringBuffer foo = new StringBuffer("");
return streamHTTPData(in, out, foo, waitForDisconnect);
}
private int streamHTTPData (InputStream in, OutputStream out,
StringBuffer host, boolean waitForDisconnect)
{
// get the HTTP data from an InputStream, and send it to
// the designated OutputStream
StringBuffer header = new StringBuffer("");
String data = "";
int responseCode = 200;
int contentLength = 0;
int pos = -1;
int byteCount = 0;
try
{
// get the first line of the header, so we know the response code
data = readLine(in);
if (data != null)
{
header.append(data + "\r\n");
pos = data.indexOf(" ");
if ((data.toLowerCase().startsWith("http")) &&
(pos >= 0) && (data.indexOf(" ", pos+1) >= 0))
{
String rcString = data.substring(pos+1, data.indexOf(" ", pos+1));
try
{
responseCode = Integer.parseInt(rcString);
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error parsing response code " + rcString);
}
}
}
// get the rest of the header info
while ((data = readLine(in)) != null)
{
// the header ends at the first blank line
if (data.length() == 0)
break;
header.append(data + "\r\n");
// check for the Host header
pos = data.toLowerCase().indexOf("host:");
if (pos >= 0)
{
host.setLength(0);
host.append(data.substring(pos + 5).trim());
}
// check for the Content-Length header
pos = data.toLowerCase().indexOf("content-length:");
if (pos >= 0)
contentLength = Integer.parseInt(data.substring(pos + 15).trim());
}
// add a blank line to terminate the header info
header.append("\r\n");
// convert the header to a byte array, and write it to our stream
out.write(header.toString().getBytes(), 0, header.length());
// if the header indicated that this was not a 200 response,
// just return what we've got if there is no Content-Length,
// because we may not be getting anything else
if ((responseCode != 200) && (contentLength == 0))
{
out.flush();
return header.length();
}
// get the body, if any; we try to use the Content-Length header to
// determine how much data we're supposed to be getting, because
// sometimes the client/server won't disconnect after sending us
// information...
if (contentLength > 0)
waitForDisconnect = false;
if ((contentLength > 0) || (waitForDisconnect))
{
try {
byte[] buf = new byte[4096];
int bytesIn = 0;
while ( ((byteCount < contentLength) || (waitForDisconnect))
&& ((bytesIn = in.read(buf)) >= 0) )
{
out.write(buf, 0, bytesIn);
byteCount += bytesIn;
}
} catch (Exception e) {
String errMsg = "Error getting HTTP body: " + e;
if (debugLevel > 0)
debugOut.println(errMsg);
//bs.write(errMsg.getBytes(), 0, errMsg.length());
}
}
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error getting HTTP data: " + e);
}
//flush the OutputStream and return
try { out.flush(); } catch (Exception e) {}
return (header.length() + byteCount);
}
private String readLine (InputStream in)
{
// reads a line of text from an InputStream
StringBuffer data = new StringBuffer("");
int c;
try
{
// if we have nothing to read, just return null
in.mark(1);
if (in.read() == -1)
return null;
else
in.reset();
while ((c = in.read()) >= 0)
{
// check for an end-of-line character
if ((c == 0) || (c == 10) || (c == 13))
break;
else
data.append((char)c);
}
// deal with the case where the end-of-line terminator is \r\n
if (c == 13)
{
in.mark(1);
if (in.read() != 10)
in.reset();
}
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error getting header: " + e);
}
// and return what we have
return data.toString();
}
}
Problem is secure sites like "https://www.google.com" don't work. I have tried to tweak the code over and over again but all to no avail. I have gone through questions answered here and many more sites too but I just cant seem to get it to work. I would av posted links but I cant cos I dnt av enuf reputation yet.
Someone pls help me with what needs to be done to support Secure Sites(HTTPS).
Thanks in advance.
PS: Sorry if I didn't ask the question the right way.I'm a newbie. Cheers...
Default port for https is 443. This is used if no port is specified in the URL, as is the case with the google site you give as an example. Try adjusting the code with this in mind.
I want to run the java code in command prompt.getting error: class interface or enum expected.Where to include packages(class files) in java file when java file need to run in command prompt..
My java code is:
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import java.org.xiph.speex.AudioFileWriter;
import org.xiph.speex.OggSpeexWriter;
import org.xiph.speex.PcmWaveWriter;
import java.org.xiph.speex.RawWriter;
import javax.sound.sampled.AudioFileWriter;
/**
* Java Speex Command Line Encoder.
*
* Currently this code has been updated to be compatible with release 1.0.3.
*
* #author Marc Gimpel, Wimba S.A. (mgimpel#horizonwimba.com)
* #version $Revision: 1.5 $
*/
public class JSpeexEnc
{
/** Version of the Speex Encoder */
public static final String VERSION = "Java Speex Command Line Encoder v0.9.7 ($Revision: 1.5 $)";
/** Copyright display String */
public static final String COPYRIGHT = "Copyright (C) 2002-2004 Wimba S.A.";
/** Print level for messages : Print debug information */
public static final int DEBUG = 0;
/** Print level for messages : Print basic information */
public static final int INFO = 1;
/** Print level for messages : Print only warnings and errors */
public static final int WARN = 2;
/** Print level for messages : Print only errors */
public static final int ERROR = 3;
/** Print level for messages */
protected int printlevel = INFO;
/** File format for input or output audio file: Raw */
public static final int FILE_FORMAT_RAW = 0;
/** File format for input or output audio file: Ogg */
public static final int FILE_FORMAT_OGG = 1;
/** File format for input or output audio file: Wave */
public static final int FILE_FORMAT_WAVE = 2;
/** Defines File format for input audio file (Raw, Ogg or Wave). */
protected int srcFormat = FILE_FORMAT_OGG;
/** Defines File format for output audio file (Raw or Wave). */
protected int destFormat = FILE_FORMAT_WAVE;
/** Defines the encoder mode (0=NB, 1=WB and 2=UWB). */
protected int mode = -1;
/** Defines the encoder quality setting (integer from 0 to 10). */
protected int quality = 8;
/** Defines the encoders algorithmic complexity. */
protected int complexity = 3;
/** Defines the number of frames per speex packet. */
protected int nframes = 1;
/** Defines the desired bitrate for the encoded audio. */
protected int bitrate = -1;
/** Defines the sampling rate of the audio input. */
protected int sampleRate = -1;
/** Defines the number of channels of the audio input (1=mono, 2=stereo). */
protected int channels = 1;
/** Defines the encoder VBR quality setting (float from 0 to 10). */
protected float vbr_quality = -1;
/** Defines whether or not to use VBR (Variable Bit Rate). */
protected boolean vbr = false;
/** Defines whether or not to use VAD (Voice Activity Detection). */
protected boolean vad = false;
/** Defines whether or not to use DTX (Discontinuous Transmission). */
protected boolean dtx = false;
/** The audio input file */
protected String srcFile;
/** The audio output file */
protected String destFile;
public AudioFileFormat.Type[] getAudioFileTypes() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
//#Override
public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
//#Override
public int write(AudioInputStream stream, AudioFileFormat.Type type, OutputStream out) throws IOException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
// #Override
public int write(AudioInputStream stream, AudioFileFormat.Type type, File file) throws IOException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
/**
* Builds a plain JSpeex Encoder with default values.
*/
/**
*
* #author Administrator
*/
/**
* Command line entrance:
* <pre>
* Usage: JSpeexEnc [options] input_file output_file
* </pre>
* #param args Command line parameters.
* #exception IOException
*/
}
/**
*
* #author Administrator
*/
public JSpeexEnc()
{
}
public static void main(final String[] args)
throws IOException
{
JSpeexEnc encoder = new JSpeexEnc();
if (encoder.parseArgs(args))
{
encoder.encode();
}
}
public boolean parseArgs(final String[] args, String srcFile, String destFile, int complexity, int nframes, boolean vbr, boolean vad, boolean dtx, int sampleRate, int channels, int mode, int quality, float vbr_quality, boolean printlevel, boolean WARN)
{
// make sure we have command args
if (args.length < 2) {
if (args.length==1 && (args[0].equalsIgnoreCase("-v") || args[0].equalsIgnoreCase("--version"))) {
version();
return false;
}
usage();
return false;
}
// Determine input, output and file formats
srcFile = args[args.length-2];
destFile = args[args.length-1];
if (srcFile.toLowerCase().endsWith(".wav"))
{
srcFormat = FILE_FORMAT_WAVE;
}
else
{
srcFormat = FILE_FORMAT_RAW;
}
if (destFile.toLowerCase().endsWith(".spx")) {
destFormat = FILE_FORMAT_OGG;
}
else if (destFile.toLowerCase().endsWith(".wav")) {
destFormat = FILE_FORMAT_WAVE;
}
else {
destFormat = FILE_FORMAT_RAW;
}
// Determine encoder options
for (int i=0; i<args.length-2; i++) {
if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--help")) {
usage();
return false;
}
else if (args[i].equalsIgnoreCase("-v") || args[i].equalsIgnoreCase("--version")) {
version();
return false;
}
else if (args[i].equalsIgnoreCase("--verbose")) {
printlevel = DEBUG;
}
else if (args[i].equalsIgnoreCase("--quiet")) {
printlevel = WARN;
}
else if (args[i].equalsIgnoreCase("-n") ||
args[i].equalsIgnoreCase("-nb") ||
args[i].equalsIgnoreCase("--narrowband")) {
mode = 0;
}
else if (args[i].equalsIgnoreCase("-w") ||
args[i].equalsIgnoreCase("-wb") ||
args[i].equalsIgnoreCase("--wideband")) {
mode = 1;
}
else if (args[i].equalsIgnoreCase("-u") ||
args[i].equalsIgnoreCase("-uwb") ||
args[i].equalsIgnoreCase("--ultra-wideband")) {
mode = 2;
}
else if (args[i].equalsIgnoreCase("-q") || args[i].equalsIgnoreCase("--quality")) {
try {
vbr_quality = Float.parseFloat(args[++i]);
quality = (int) vbr_quality;
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("-complexity")) {
try {
complexity = Integer.parseInt(args[++i]);
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--nframes")) {
try {
nframes = Integer.parseInt(args[++i]);
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--vbr")) {
vbr = true;
}
else if (args[i].equalsIgnoreCase("--vad")) {
vad = true;
}
else if (args[i].equalsIgnoreCase("--dtx")) {
dtx = true;
}
else if (args[i].equalsIgnoreCase("--rate")) {
try {
sampleRate = Integer.parseInt(args[++i]);
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--stereo")) {
channels = 2;
}
else {
usage();
return false;
}
}
return true;
}
/**
* Prints the usage guidelines.
*/
public static void usage()
{
version();
System.out.println("");
System.out.println("Usage: JSpeexEnc [options] input_file output_file");
System.out.println("Where:");
System.out.println(" input_file can be:");
System.out.println(" filename.wav a PCM wav file");
System.out.println(" filename.* a raw PCM file (any extension other than .wav)");
System.out.println(" output_file can be:");
System.out.println(" filename.spx an Ogg Speex file");
System.out.println(" filename.wav a Wave Speex file (beta!!!)");
System.out.println(" filename.* a raw Speex file");
System.out.println("Options: -h, --help This help");
System.out.println(" -v, --version Version information");
System.out.println(" --verbose Print detailed information");
System.out.println(" --quiet Print minimal information");
System.out.println(" -n, -nb Consider input as Narrowband (8kHz)");
System.out.println(" -w, -wb Consider input as Wideband (16kHz)");
System.out.println(" -u, -uwb Consider input as Ultra-Wideband (32kHz)");
System.out.println(" --quality n Encoding quality (0-10) default 8");
System.out.println(" --complexity n Encoding complexity (0-10) default 3");
System.out.println(" --nframes n Number of frames per Ogg packet, default 1");
System.out.println(" --vbr Enable varible bit-rate (VBR)");
System.out.println(" --vad Enable voice activity detection (VAD)");
System.out.println(" --dtx Enable file based discontinuous transmission (DTX)");
System.out.println(" if the input file is raw PCM (not a Wave file)");
System.out.println(" --rate n Sampling rate for raw input");
System.out.println(" --stereo Consider input as stereo");
System.out.println("More information is available from: http://jspeex.sourceforge.net/");
System.out.println("This code is a Java port of the Speex codec: http://www.speex.org/");
}
/**
* Prints the version.
* #param COPYRIGHT
*/
public static void version(boolean COPYRIGHT)
{
System.out.println(VERSION);
System.out.println("using " + SpeexEncoder.VERSION);
System.out.println(COPYRIGHT);
}
/**
* Encodes a PCM file to Speex.
* #param srcFile
* #exception IOException
*/
public void encode(String srcFile)
throws IOException
{
encode(new File(srcFile), new File(destFile));
}
/**
* Encodes a PCM file to Speex.
* #param srcPath
* #param destPath
* #param channels
* #param sampleRate
* #exception IOException
*/
public void encode(final File srcPath, final File destPath, int channels, int sampleRate, boolean printlevel, boolean DEBUG, String vbr, int nframes, String vbr_quality)
throws IOException
{
byte[] temp = new byte[2560]; // stereo UWB requires one to read 2560b
final int HEADERSIZE = 8;
final String RIFF = "RIFF";
final String WAVE = "WAVE";
final String FORMAT = "fmt ";
final String DATA = "data";
final int WAVE_FORMAT_PCM = 0x0001;
// Display info
if (printlevel <= INFO) version();
if (printlevel <= DEBUG) System.out.println("");
if (printlevel <= DEBUG) System.out.println("Input File: " + srcPath);
try (DataInputStream dis = new DataInputStream(new FileInputStream(srcPath))) {
int mode;
// Prepare input stream
if (srcFormat == FILE_FORMAT_WAVE) {
// read the WAVE header
dis.readFully(temp, 0, HEADERSIZE+4);
// make sure its a WAVE header
if (!RIFF.equals(new String(temp, 0, 4)) &&
!WAVE.equals(new String(temp, 8, 4))) {
System.err.println("Not a WAVE file");
return;
}
// Read other header chunks
dis.readFully(temp, 0, HEADERSIZE);
String chunk = new String(temp, 0, 4);
int size = readInt(temp, 4);
while (!chunk.equals(DATA)) {
dis.readFully(temp, 0, size);
if (chunk.equals(FORMAT)) {
/*
typedef struct waveformat_extended_tag {
WORD wFormatTag; // format type
WORD nChannels; // number of channels (i.e. mono, stereo...)
DWORD nSamplesPerSec; // sample rate
DWORD nAvgBytesPerSec; // for buffer estimation
WORD nBlockAlign; // block size of data
WORD wBitsPerSample; // Number of bits per sample of mono data
WORD cbSize; // The count in bytes of the extra size
} WAVEFORMATEX;
*/
if (readShort(temp, 0) != WAVE_FORMAT_PCM) {
System.err.println("Not a PCM file");
return;
}
channels = readShort(temp, 2);
sampleRate = readInt(temp, 4);
if (readShort(temp, 14) != 16) {
System.err.println("Not a 16 bit file " + readShort(temp, 18));
return;
}
// Display audio info
if (printlevel <= DEBUG) {
System.out.println("File Format: PCM wave");
System.out.println("Sample Rate: " + sampleRate);
System.out.println("Channels: " + channels);
}
}
dis.readFully(temp, 0, HEADERSIZE);
chunk = new String(temp, 0, 4);
size = readInt(temp, 4);
}
if (printlevel <= DEBUG) System.out.println("Data size: " + size);
}
else {
if (sampleRate < 0) {
switch (mode) {
case 0:
sampleRate = 8000;
break;
case 1:
sampleRate = 16000;
break;
case 2:
sampleRate = 32000;
break;
default:
sampleRate = 8000;
break;
}
}
// Display audio info
if (printlevel <= DEBUG) {
System.out.println("File format: Raw audio");
System.out.println("Sample rate: " + sampleRate);
System.out.println("Channels: " + channels);
System.out.println("Data size: " + srcPath.length());
}
}
// Set the mode if it has not yet been determined
if (mode < 0) {
if (sampleRate < 100) // Sample Rate has probably been given in kHz
sampleRate *= 1000;
if (sampleRate < 12000)
mode = 0; // Narrowband
else if (sampleRate < 24000)
mode = 1; // Wideband
else
mode = 2; // Ultra-wideband
}
// Construct a new encoder
SpeexEncoder speexEncoder = new SpeexEncoder();
speexEncoder.init(mode, quality, sampleRate, channels);
if (complexity > 0) {
speexEncoder.getEncoder().setComplexity(complexity);
}
if (bitrate > 0) {
speexEncoder.getEncoder().setBitRate(bitrate);
}
if (vbr) {
speexEncoder.getEncoder().setVbr(vbr);
if (vbr_quality > 0) {
speexEncoder.getEncoder().setVbrQuality(vbr_quality);
}
}
if (vad) {
speexEncoder.getEncoder().setVad(vad);
}
if (dtx) {
speexEncoder.getEncoder().setDtx(dtx);
}
// Display info
if (printlevel <= DEBUG) {
System.out.println("");
System.out.println("Output File: " + destPath);
System.out.println("File format: Ogg Speex");
System.out.println("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband")));
System.out.println("Quality: " + (vbr ? vbr_quality : quality));
System.out.println("Complexity: " + complexity);
System.out.println("Frames per packet: " + nframes);
System.out.println("Varible bitrate: " + vbr);
System.out.println("Voice activity detection: " + vad);
System.out.println("Discontinouous Transmission: " + dtx);
}
// Open the file writer
AudioFileWriter writer;
if (destFormat == FILE_FORMAT_OGG) {
writer = new OggSpeexWriter(mode, sampleRate, channels, nframes, vbr);
}
else if (destFormat == FILE_FORMAT_WAVE) {
nframes = PcmWaveWriter.WAVE_FRAME_SIZES[mode-1][channels-1][quality];
writer = new PcmWaveWriter(mode, quality, sampleRate, channels, nframes, vbr);
}
else {
writer = new RawWriter();
}
writer.open(destPath);
writer.writeHeader("Encoded with: " + VERSION);
int pcmPacketSize = 2 * channels * speexEncoder.getFrameSize();
while (true) {
dis.readFully(temp, 0, nframes*pcmPacketSize);
for (int i=0; i<nframes; i++)
speexEncoder.processData(temp, i*pcmPacketSize, pcmPacketSize);
int encsize = speexEncoder.getProcessedData(temp, 0);
if (encsize > 0) {
writer.writePacket(temp, 0, encsize);
}
}
writer.close();
}
}
/**
* Converts Little Endian (Windows) bytes to an int (Java uses Big Endian).
* #param data the data to read.
* #param offset the offset from which to start reading.
* #return the integer value of the reassembled bytes.
*/
protected static int readInt(final byte[] data, final int offset)
{
return (data[offset] & 0xff) |
((data[offset+1] & 0xff) << 8) |
((data[offset+2] & 0xff) << 16) |
(data[offset+3] << 24); // no 0xff on the last one to keep the sign
}
/**
* Converts Little Endian (Windows) bytes to an short (Java uses Big Endian).
* #param data the data to read.
* #param offset the offset from which to start reading.
* #return the integer value of the reassembled bytes.
*/
protected static int readShort(final byte[] data, final int offset)
{
return (data[offset] & 0xff) |
(data[offset+1] << 8); // no 0xff on the last one to keep the sign
}
}
I've created an android application in which the Android application acts as the client and server resides on a desktop. I'm using socket programming for communication. I've successfully transferred messages between client and server, but I don't know how to transfer an image. I need to send image file from server to client, not from client to server
Can anyone please help me with the solution for sending a png image from server to client?
This is my code so far:
Client side
private int SERVER_PORT = 9999;
class Client implements Runnable {
private Socket client;
private PrintWriter out;
private Scanner in;
#Override
public void run() {
try {
client = new Socket("localhost", SERVER_PORT);
Log.d("Client", "Connected to server at port " + SERVER_PORT);
out = new PrintWriter(client.getOutputStream());
in = new Scanner(client.getInputStream());
String line;
while ((line = in.nextLine()) != null) {
Log.d("Client", "Server says: " + line);
if (line.equals("Hello client")) {
out.println("Reply");
out.flush();
}
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Server class
class ServerThread implements Runnable {
private ServerSocket server;
#Override
public void run() {
try {
server = new ServerSocket(SERVER_PORT);
Log.d("Server", "Start the server at port " + SERVER_PORT
+ " and waiting for clients...");
while (true) {
Socket socket = server.accept();
Log.d("Server",
"Accept socket connection: "
+ socket.getLocalAddress());
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
private Socket clientSocket;
private PrintWriter out;
private Scanner in;
public ClientHandler(Socket clietSocket) {
this.clientSocket = clietSocket;
}
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream());
in = new Scanner(clientSocket.getInputStream());
String line;
Log.d("ClientHandlerThread", "Start communication with : "
+ clientSocket.getLocalAddress());
out.println("Hello client");
out.flush();
while ((line = in.nextLine()) != null) {
Log.d("ClientHandlerThread", "Client says: " + line);
if (line.equals("Reply")){
out.print("Server replies");
out.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here you have server and client codes that send/receive (image) files from server to client.
Client save the image in external storage, change that if you want to save it somewhere else.
The client function returns a Bitmap of the received image, you can also avoid this by commenting the lines in the code.
To use the functions, use something similar to the following: NOTE these two function must be called from a thread other than the main UI thread:
// To receive a file
try
{
// The file name must be simple file name, without file separator '/'
receiveFile(myClientSocket.getInputStream(), "myImage.png");
}
catch (Exception e)
{
e.printStackTrace();
}
// to send a file
try
{
// The file name must be a fully qualified path
sendFile(myServerSocket.getOutputStream(), "C:/MyImages/orange.png");
}
catch (Exception e)
{
e.printStackTrace();
}
The receiver function: (Copy and paste it to the client side)
/**
* Receive an image file from a connected socket and save it to a file.
* <p>
* the first 4 bytes it receives indicates the file's size
* </p>
*
* #param is
* InputStream from the connected socket
* #param fileName
* Name of the file to save in external storage, without
* File.separator
* #return Bitmap representing the image received o null in case of an error
* #throws Exception
* #see {#link sendFile} for an example how to send the file at other side.
*
*/
public Bitmap receiveFile(InputStream is, String fileName) throws Exception
{
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileInES = baseDir + File.separator + fileName;
// read 4 bytes containing the file size
byte[] bSize = new byte[4];
int offset = 0;
while (offset < bSize.length)
{
int bRead = is.read(bSize, offset, bSize.length - offset);
offset += bRead;
}
// Convert the 4 bytes to an int
int fileSize;
fileSize = (int) (bSize[0] & 0xff) << 24
| (int) (bSize[1] & 0xff) << 16
| (int) (bSize[2] & 0xff) << 8
| (int) (bSize[3] & 0xff);
// buffer to read from the socket
// 8k buffer is good enough
byte[] data = new byte[8 * 1024];
int bToRead;
FileOutputStream fos = new FileOutputStream(fileInES);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (fileSize > 0)
{
// make sure not to read more bytes than filesize
if (fileSize > data.length) bToRead = data.length;
else bToRead = fileSize;
int bytesRead = is.read(data, 0, bToRead);
if (bytesRead > 0)
{
bos.write(data, 0, bytesRead);
fileSize -= bytesRead;
}
}
bos.close();
// Convert the received image to a Bitmap
// If you do not want to return a bitmap comment/delete the folowing lines
// and make the function to return void or whatever you prefer.
Bitmap bmp = null;
FileInputStream fis = new FileInputStream(fileInES);
try
{
bmp = BitmapFactory.decodeStream(fis);
return bmp;
}
finally
{
fis.close();
}
}
The sender function: (copy and paste it to the server side)
/**
* Send a file to a connected socket.
* <p>
* First it sends file size in 4 bytes then the file's content.
* </p>
* <p>
* Note: File size is limited to a 32bit signed integer, 2GB
* </p>
*
* #param os
* OutputStream of the connected socket
* #param fileName
* The complete file's path of the image to send
* #throws Exception
* #see {#link receiveFile} for an example how to receive file at other side.
*
*/
public void sendFile(OutputStream os, String fileName) throws Exception
{
// File to send
File myFile = new File(fileName);
int fSize = (int) myFile.length();
if (fSize < myFile.length())
{
System.out.println("File is too big'");
throw new IOException("File is too big.");
}
// Send the file's size
byte[] bSize = new byte[4];
bSize[0] = (byte) ((fSize & 0xff000000) >> 24);
bSize[1] = (byte) ((fSize & 0x00ff0000) >> 16);
bSize[2] = (byte) ((fSize & 0x0000ff00) >> 8);
bSize[3] = (byte) (fSize & 0x000000ff);
// 4 bytes containing the file size
os.write(bSize, 0, 4);
// In case of memory limitations set this to false
boolean noMemoryLimitation = true;
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
try
{
if (noMemoryLimitation)
{
// Use to send the whole file in one chunk
byte[] outBuffer = new byte[fSize];
int bRead = bis.read(outBuffer, 0, outBuffer.length);
os.write(outBuffer, 0, bRead);
}
else
{
// Use to send in a small buffer, several chunks
int bRead = 0;
byte[] outBuffer = new byte[8 * 1024];
while ((bRead = bis.read(outBuffer, 0, outBuffer.length)) > 0)
{
os.write(outBuffer, 0, bRead);
}
}
os.flush();
}
finally
{
bis.close();
}
}