I'd like to map a port number to a user (linux user that is running a process that is binding to the port).
How can I do it in java?
I know I can go out to the shell and run bash commands that map a port to a PID, and then PID to user, but I'd like to keep it inside java if I can.
The more general question is: I have a webapp application that receives requests from localhost, and I'd like to know which local user performed the HttpServletRequest, so I can attach proper authorities to it.
Background:
I'm using spring security for all remote connections. However, I have a small part of the application (separated from the webapp) that is running locally alongside the application server, and that application is authenticated using the linux user mechanism. So for that reason, I bypass the server authentication rules for localhost (assuming all localhost access is permitted). The problem is with authorization - I need the identify the user running the localhost requests. Any idea how can I achieve this?
This is Linux dependent code, but not difficult to port to Windows.
This is not a Servlet code, but would work in that case as well:
Lets say I've a ServerSocket waiting on accept() call. When it receives a client request, it creates a Socket at another port to deal with that 'remote' request.
ServerSocket ss = new ServerSocket(2000);
System.out.println("Listening on local port : " + ss.getLocalPort());
while(...)
{
Socket s = ss.accept();
System.out.println("accepted client request, opened local port : " + s.getPort());
...
}
So, you need to feed the output of s.getPort() from above snippet to the following program's main() method.
public class FindUserByPort
{
public static void main(String[] args) throws Exception
{
String cmd = "netstat -anp | grep ";
int port = Integer.valueOf(args[0]);
cmd = cmd + port ;
Process pr = Runtime.getRuntime().exec(cmd);
InputStream is = pr.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
List<Integer> pIDs = new ArrayList<Integer>();
while ((line = br.readLine()) != null)
{
if (line.contains("127.0.0.1:" + port))
{
String pidPname = line.substring(line.indexOf("ESTABLISHED") + "ESTABLISHED".length());
pidPname = pidPname.trim();
String pid = pidPname.split("/")[0];
pIDs.add(Integer.valueOf(pid));
}
}
if (pIDs.size() > 0)
{
for (int pid : pIDs)
{
String command = "top -n1 -b -p " + pid ;
Process p = Runtime.getRuntime().exec(command);
InputStream _is = p.getInputStream();
BufferedReader _br = new BufferedReader(new InputStreamReader(_is));
String _line = null;
while ((_line = _br.readLine()) != null)
{
_line = _line.trim();
if(_line.startsWith(String.valueOf(pid)))
{
String[] values = _line.split(" ");
System.out.println("pid : " + pid + ", user : " + values[1]);
}
}
_is.close();
_br.close();
}
}
is.close();
br.close();
}
}
Related
I'm trying to run python script from java and when something would change in java I want to send information about it to python program. I don't know the best solution for it. I can run python script and send start information to it but then problems start. I think about sending data through tcp/ip connection, but when I try to do that I have error in python script:
Caused by: Traceback (most recent call last):
File "pythonScript.py", line 2, in <module>
import socket
ImportError: No module named socket
at org.python.core.Py.ImportError(Py.java:264)
at org.python.core.imp.import_first(imp.java:657)
at org.python.core.imp.import_name(imp.java:741)
at org.python.core.imp.importName(imp.java:791)
at org.python.core.ImportFunction.__call__(__builtin__.java:1236)
at org.python.core.PyObject.__call__(PyObject.java:367)
at org.python.core.__builtin__.__import__(__builtin__.java:1207)
at org.python.core.__builtin__.__import__(__builtin__.java:1190)
at org.python.core.imp.importOne(imp.java:802)
at org.python.pycode._pyx0.f$0(pythonScript.py:27)
at org.python.pycode._pyx0.call_function(pythonScript.py)
at org.python.core.PyTableCode.call(PyTableCode.java:165)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1197)
at org.python.core.__builtin__.execfile_flags(__builtin__.java:538)
at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:156)
at sample.PythonClass.runPythonScript(PythonClass.java:26)
at sample.Controller.handleSubmitButtonActionIp(Controller.java:30)
... 58 more
So it's some problem with scoket import, but when I run this program normaly there is no error. It's code of function which I use to run python script:
public void runPythonScript(boolean isCameraOn, String ip){
System.out.println(ip);
String[] arguments = {ip};
PythonInterpreter.initialize(System.getProperties(),System.getProperties(), arguments);
PythonInterpreter python = new PythonInterpreter();
StringWriter out = new StringWriter();
python.setOut(out);
python.execfile("pythonScript.py");
String outputStr = out.toString();
System.out.println(outputStr);
}
And it's code of python client:
import sys
import socket //ERROR
print("poczatek")
print(sys.argv[0])
print("koniec")
HOST = "localhost"
PORT = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.connect((HOST, PORT))
sock.sendall("Hello\n")
data = sock.recv(1024)
print("1)", data)
if (data == "olleH\n"):
sock.sendall("Bye\n")
data = sock.recv(1024)
print("2)", data)
if (data == "eyB}\n"):
sock.close()
print("Socket closed")
Java server:
public void sendDataToPythonScript(boolean isCameraOn, String ip) throws
IOException {
String fromClient;
String toClient;
ServerSocket server = new ServerSocket(8080);
System.out.println("wait for connection on port 8080");
boolean run = true;
while(run) {
Socket client = server.accept();
System.out.println("got connection on port 8080");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(),true);
fromClient = in.readLine();
System.out.println("received: " + fromClient);
if(fromClient.equals("Hello")) {
toClient = "olleH";
System.out.println("send olleH");
out.println(toClient);
fromClient = in.readLine();
System.out.println("received: " + fromClient);
if(fromClient.equals("Bye")) {
toClient = "eyB";
System.out.println("send eyB");
out.println(toClient);
client.close();
run = false;
System.out.println("socket closed");
}
}
}
System.exit(0);
}
Try importing the embedded socket module
import _socket
If that does not fix it try setting the path for python modules this link should explain how to set the path for python in java.
I have a TCP client application in Java, through this application i can communicate with a server application.
I have a simple method sendCommand which sends the message to the server:
void sendCommand(String command) throws IOException {
String ipaddress = "192.168.0.2";
Socket commandSocket = null;
PrintWriter out = null;
BufferedWriter out = null;
BufferedReader in = null;
BufferedWriter outToDetailFile = null;
FileWriter fstream = null;
String version = "";
int numberOfBallsInGame;
int ledCycleState = 1;
commandSocket = new Socket(ipaddress, 7420);
out = new BufferedWriter(new OutputStreamWriter(commandSocket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(commandSocket.getInputStream()));
out.write("c");out.flush();
out.write(command);out.flush();
String message = in.readLine();
//System.out.println(message);
out.close();
in.close();
commandSocket.close();
}
Now, because the server application is on the machine which does not accept more than 2 connections in 20 seconds i need to modify my method and "split" it in 3 different methods (i think).
My plan is the following:
I would like to call the connection to the server in one thread, keep it opened untill i want to close it, but i should be able to send the commands between opening the connection and closing it.
I'm pretty new to Java and i'll try to explain here exactly what i want to do:
1) I want to open the connection to TCP server.
2) After opening the connection i want to be able to send commands to an already opened connection by calling this method:
void sendCommand(String command) throws IOException {
out.write("c");out.flush();
out.write(command);out.flush();
}
And after i'm finished with sending commands i want to call some method to close my running connection.
Because i'm pretty new to java it would be very nice if someone could show me how to achieve this or modify my method.
Thank you in advance,
I have a java program which accepts a http request from web browser and in response, program sends a text file contents to display in web browser. The program is working fine when I make request from browser which is installed on the same machine in which java code is running but when I make request from some other web browser which is not on the same machine as in which java code running, the program does not get any request.
This is how I make request from my web browser:-
http://localhost:port_number/
This is working fine...
This is how I make request from some other web browser which is not on my machine:
http://my_ip_address:port_number/
This is not working...
And this is my java code:-
while (true) {
ServerSocket serverSocket = null;
Socket clientSocket = null;
try {
serverSocket = new ServerSocket(32768);
clientSocket = serverSocket.accept();
InetAddress ia = clientSocket.getInetAddress();
jTextArea1.append("Connected to : " + ia + "\n");
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String inputLine, outputLine;
String s = (String) JOptionPane.showInputDialog(this, "Enter File Name : ");
File f = new File(s);
if (f.exists()) {
out.println("http/1.1 200 ok\r");
out.println("Mime version 1.1");
out.println("Content-Type: text/html\r");
out.println("Content-Length: " + f.length() + "\r");
out.println("\r");
BufferedReader d = new BufferedReader(new FileReader(s));
String line = " ", a;
while ((a = d.readLine()) != null) {
line = line + a;
}
out.write(line);
out.flush();
jTextArea1.append("File Delivered.\n");
d.close();
}
out.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
jTextArea1.append("Accept failed.");
System.exit(1);
}
}
This is not related to the code that you've written. You need to make your IP address publicly accessible. Here's is a related thread.
Check that you are indeed listening on 0.0.0.0:32768 and not 127.0.0.1:32768 or any other particulat IP (specially if you are connected to several network). Start a shell and use netstat -ano on Windows and netstat -anp on Unix or Mac.
Check that your firewall allows remote connection to the port 32768
I am trying to make a socket server, I am connecting through putty to this server. Whenever I type "hi" it says "no" rather than "hi" which I want it to do. I found this on A java website. If you could tell me what I am doing wrong that would be great. Thanks!
int port = 12345;
ServerSocket sock = new ServerSocket(port);
System.out.println("Server now active on port: " + port);
Socket link = sock.accept();
System.out.println("Interface accepted request, IP: " + link.getInetAddress());
BufferedReader input = new BufferedReader(new InputStreamReader(link.getInputStream()));
PrintWriter output = new PrintWriter(link.getOutputStream(), true);
output.println("ISEEYOU");
String inputLine;
Thread.sleep(1500);
while((inputLine = input.readLine()) != null) {
if(inputLine.equals("hi")) {
output.println("hi");
}else{
output.println("no");
}
}
Your Java program is correct.
I've tried your code, just added System.out.printf("[%s]", inputLine); as first line in the while loop to ensure, what I get from putty.
I guess your problem is the protocol putty uses to connect. It worked with RAW for me. See below the session setting I've used:
EDIT:
According to your comment I added some code for a simple client, that reads the line from console, sends it to the server and prints the echo back to console.
public void Client() throws IOException {
// Client that closes the communication when the user types "quit"
Socket socket = new Socket("localhost", 8080);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
BufferedReader user = new BufferedReader(new InputStreamReader(System.in));
String line;
while(!(line = user.readLine()).equals("quit")) {
ps.println(line); // Write to server
System.out.println(reader.readLine()); // Receive echo
}
socket.shutdownOutput(); // Send EOF to server
socket.close();
}
The corresponding server would look like this:
public void server() throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
// Just read a line and echo it till EOF
String line;
while((line = reader.readLine()) != null) ps.println(line);
}
You might need to change the port I used here, if 8080 is already binded on your machine. Also you might want to have the server running on another computer then the client. In this case you need to change "localhost".
I am running a Jetty web server and using it to execute some bash scripts depending on what parameters it receives via GET. I've never worked with Jetty, so I pieced together some stuff from here to get it working. My issue is that it idles at ~100mb of ram when there are no requests, and after about 12 hours, it idles as high as 1gb of ram. This seems like an awful lot for something that just runs a bash script if the request is legit. The average file size that the servlet ends up serving is about 400kb.
How the server is started:
public void startServer() {
String hostname = "localhost";
int port = 7500;
Server server = new Server();
Connector connector = new SelectChannelConnector();
connector.setHost(hostname);
connector.setPort(port);
server.setConnectors(new Connector[]{connector});
server.setStopAtShutdown(true);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(new ServletHolder(new DaemonServlet()), "/call/*");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { context });
server.setHandler(handlers);
server.start();
server.join();
}
The servlet (DaemonServlet):
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String msg = "";
String call = request.getParameter("call");
ProcessBuilder pb = null;
Process p = null;
switch (call) {
case "sendAction": // Sends an action to a process with a certain ID
pb = new ProcessBuilder("/bin/bash", "/opt/test/process.sh", request.getParameter("process"), request.getParameter("action"));
break;
case "getFile": // Reads the file with the given ID into a string, to be returned by Jetty
pb = new ProcessBuilder("/bin/bash", "/opt/test/getFile.sh", request.getParameter("fileId"));
try {
p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String scriptOutput = "";
String line;
while ((line = br.readLine()) != null) {
scriptOutput += line + '\n';
}
br.close();
msg = scriptOutput;
p.destroy();
p = null;
} catch (Exception e) {}
break;
}
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(msg);
}
Is there anything that seems to be set up incorrectly here?
It looks like the line:
scriptOutput += line + '\n';
is consuming a huge amount of memory. Why not write the information back through the response as you get it?
As Reimeus said, you should probably echo the output as you get it. If you go that way, you should send the response headers (content type, status code) before sending the process output.
At the very least, you should use StringBuilder instead of concatenating Strings.