Simple Java Server with PrintWriter - problem sending a response to browser - java

I've just started looking at HTTP etc. and have written a simple Java Client that uses URLConnection to send a URL to a server and pulls down the index.html page (as plain text).
Now I'm working on a simple server but I'm stuck at the first hurdle, (well maybe 2nd or 3rd), I can't get it to respond to the client properly.
Here is the reading in loop and it reads in the HTTP request fine, even from FF and IE etc:
while((message = in.readLine()) != null)
{
System.out.println(message);
out.write("something");
}
The problem is that I don't know how to get it to respond anything useful. If I let it do what it is doing in the above code it sends "something" 6 times to my client (as there are 6 lines to the HTTP request) but nothing to FF/IE etc.
Also, it doesn't seem to break the loop ever as I added a System.out.println("test"); line to print after the loop but the server never seems to reach that point, should it? Should readLine() return null at the end of the first HTTP request?
I've been reading stuff on the sun and oracle websites but am still pretty stuck as to how this should work.
Thanks for your time,
Infinitifizz
EDIT: Oops, forgot to copy the code in.
Server.java:
package exercise2;
import java.net.*;
public class Server
{
public static void main(String[] args) throws Exception
{
boolean listening = true;
ServerSocket server = new ServerSocket(8081);
while(listening)
{
Socket client = server.accept();
new ServerThread(client).start();
}
server.close();
}
}
ServerThread.java:
package exercise2;
import java.io.*;
import java.net.*;
public class ServerThread extends Thread
{
private Socket socket = null;
public ServerThread(Socket s)
{
this.socket = s;
}
public void run()
{
try
{
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String message, reply = "";
while((message = in.readLine()) != null)
{
System.out.println(message);
out.write("something");
}
System.out.println("test");
in.close();
out.close();
socket.close();
}
catch(IOException e)
{
System.err.println("error");
}
}
}

Without seeing your client code, this is my best guess as to what's happening:
Your server is probably blocking in that readLine() because the client is done writing the request, but hasn't closed the connection (as it should: the client should wait around to get the response over that same connection). Typically, a HTTP server parses a request as it reads it: based on this, you can look for "\r\n\r\n" to demarcate the end of the header, and break out of your read loop at that point to parse the request and respond to it.

First of all, change the condition in the while loop to
while(in.hasNextLine()) {
message = in.nextLine();
//etc....
Secondly, you don't need to exit out of the while loop while running a server. You should do all the parsing for requests inside the while loop, using if statements to distinguish the requests. The only time you would ever exit the while loop is when the connection should close, otherwise, the nextLine() method will block until something is received.

Related

how to prevent 429 to many requests while sending messages to telegram bot

i have an api which receives data from a source and send them to telegram bot.
i receive data in bulk from my source and will send them to telegram bot with that rate but telegram can handle only 1 message per sec so eventually it returning this exception
java.io.IOException: Server returned HTTP response code: 429 for URL:....
is there a way to store messages in list and iterate this list from a thread
am trying to learn java so please don't mind if my code not good.
Sample.java
class Sample{
run(){
while(true){
//some operations
SendMessage.getInstance().sendToTelegram(clientCommand);
//
}
}
}
SendMessage.java
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class SendMessage {
static SendMessage getInstance() {
return instance;
}
public void sendToTelegram(String message) {
String urlString = "https://api.telegram.org/;
String apiToken = obj.getInstance().getTelegramToken();
String chatId = obj.getInstance().getChatId();
String text = message;
urlString = urlString+"/bot"+apiToken+"/sendMessage?parse_mode=HTML&chat_id="+chatId+"&text="+msgToSend;
try {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
InputStream is = new BufferedInputStream(conn.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String inputLine = "";
StringBuilder sb = new StringBuilder();
while ((inputLine = br.readLine()) != null) {
sb.append(inputLine);
sb.append('\r');
}
br.close();
} catch (IOException e) {
log.error(e);
}
}
}
if thread concept works can anyone please help me how to add into a list and send them to telegram bot without loosing data
by using sleeping thread am not getting 429 too many responses exception
class Sample{
run(){
while(true){
//some operations
SendMessage.getInstance().sendToTelegram(clientCommand);
Thread.sleep(2000);
}
}
}
but getting new exceptions bad request
java.io.IOException: Server returned HTTP response code: 400 for URL
and this is the demo telegram url
https://api.telegram.org/botid:TELEGRAM_TOKEN/sendMessage?parse_mode=HTML&chat_id=CHAT_ID&text=<b>Alert</b>%0A<b>Alert Name:</b> "REGISTER Violation"%0A<b>Severity:</b> "Medium"%0A<b>TimeStamp:</b> "2022-05-10 22:17:34.31"%0A<b>Event ID:</b> "160"%0A<b>Event Message:</b> "An unregistered User has been detected. This can be a Caller-ID poisoning or Number Harvesting attack. Only a valid registered user can make or receive calls"%0A<b>Source Contact:</b> "192.168.3.31:5077"%0A<b>Destination Contact:</b> "192.168.10.10:5555"%0A<b>Source IP:</b> "192.168.3.31"%0A<b>Destination IP:</b> "192.168.10.10"%0A<b>Source Ext:</b> "4545454545"%0A<b>Destination Ext:</b> "%2B43965272"%0A<b>Source Domain:</b> "n/a"%0A<b>Destination Domain:</b> "n/a"%0A<b>Protocol:</b> "SIP"%0A<b>Comment:</b> "None"%0A<b>Attack Name:</b> "REGISTER Violation"%0A<b>Method:</b> "INVITE"%0A<b>Source Country:</b> "Unknown"%0A<b>Destination Country:</b> "AUSTRIA"%0A<b>CallType:</b> "International"%0A<b>RiskScore:</b> "0"%0A<b>Client Name:</b> "Unknown:Unknown"%0A<b>Network Group Name:</b> "defaultNonVlanGroup"%0A<b>Acknowledged:</b> "No"%0A<b>Alert Category:</b> "External"%0A<b>UCTM Name:</b> "redshift"
and i tried manually by pasting url which shown in exception but its worked fine but in application its throwing this exception
Please help where i am doing wrong
You could just do a simple Thread.sleep(2000) in your loop. Might not scale too good
Or you could store all your messages in a synchronzied list (https://www.techiedelight.com/queue-implementation-in-java/) and make a scheduler that would read a message every x seconds, send it and delete it from the list. If your using Spring Boot this is pretty easy -> https://www.baeldung.com/spring-task-scheduler

After successfully establishing a socket connection, how does the server actively send string messages to the client?

I am building a server. I hope that after the Java server and the C# client are connected, I can send information from the HTML to the Java server, and then the Java server sends this information to the client.But I can't get the socket after the successful establishment in the service layer, so my Java server can only send fixed information to the client.
I tried using Class object = new Class(); object.setObject(socket); to save the socket, but when I call this object in the service layer, I get null;
I tried to save the socket using (Map) socket.put("socket", socket), but when I call this method in the service layer, I get null.
This is the code to make the socket. from SocketThread.java
public void run() {
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(5656);
LOGGER.info("socket server start, monitor 5656 port ! ");
Socket socket = serverSocket.accept();
new SocketClientRequest(socket).start();
LOGGER.info("send success ! ");
}catch (Exception ex){
LOGGER.error("send fail ! ");
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
LOGGER.error("服务器延时重启失败 ! ");
}
}
This is a method of reading the information sent by the client using the socket and sending the information to the client. from SocketClientRequest.java
public void run() {
try {
//获取socket中的数据
bufferedInputStream = new
BufferedInputStream(socket.getInputStream());
byte[] clientCharStream = new byte[messageLengthBytes];
bufferedInputStream.read(clientCharStream);
System.out.println(new String(clientCharStream, "utf-8"));
OutputStream out = socket.getOutputStream();
out.write(new String("welcome_send_server!").getBytes());
} catch (IOException e) {
LOGGER.error("read massage error [{}]", e);
}
}
Create a connection when the project starts
#EnableScheduling
#SpringBootApplication
public class GzserverApplication {
public static void main(String[] args) {
SpringApplication.run(GzserverApplication.class, args);
SocketServer socketServer = new SocketServer();
socketServer.start();
}
}
Until this step, everything is fine, but the key problem is coming.
I need to send information to the client through my controller.
this is controller
#ResponseBody
#RequestMapping(value = "firstSend)
public SResult<String> firstSend(String uName, String pNum, String time){
try{
return httpService.firstSend(uName, pNum, time);
}catch (Exception ex){
LOGGER.error(ex.getMessage(), ex);
}
return SResult.failure("fail of connect");
}
this is service
public SResult<String> firstSend(String uName, String pNum, String time) throws Exception {
String token = TokenUtil.sign(uName);
System.out.println("token code : "+token);
SocketObject socketObject = new SocketObject();
Map<String, Socket> socketMap = socketObject.socket();
Socket socket1 = socketMap.get("Socket"); // is null
Socket socket2 = socketObject.getSocket(); // is null
return SResult.success(token);
}
I hope that after the connection is successfully created, the socket can be used in the service layer, and the information is sent to the client through the socket, but no matter what I do, the socket is null in the service layer.please give me a help, thank you very much
You should not be dealing with Sockets if using Spring. Spring is a very extensive abstraction layer, that lets you avoid having to deal with the nasty details that Sockets introduce.
In your controller, you call: SocketObject socketObject = new SocketObject(); This creates a new object, presumably with a null-initialized Socket object. Nowhere in this code do you pass a socket object from the main() scope to any other scope (for example using a method named setSocket(Socket socket).
However, and I cannot stress this enough, you should not use Sockets in Spring. Think about what problem you are trying to solve, and ask yourself (why do I need to send information to the client). It is likely that Spring has a module that will do this for you in a much more scalable and manageable way.
For example, perhaps you need to establish 2-way communication between the server and the client, and need to post information to the client periodically. In this case, the WebSocket protocol (and associated Spring Websocket library) might be for you.
This is likely an XY problem. If you edit your question to illustrate the functionality you are trying to implement, it may be easier to help

Java Sockets: One Server and Multiple Clients

So I created a basic client-server program in java. It starts out like this:
Client connects to Server
Server asks for Client's name
Client responds with name
Server greets Client
After this, Client speaks and the Server repeats the words back
I got this to work without too much trouble using this tutorial. The problem comes whenever I try to introduce multiple clients. I thought that it would work because I'm using multiple threads, however, the second clients just hangs until the first client quits and then it starts it work (the server does accept input from the second client, but it doesn't respond with anything until the first client quits).
Here is the code I'm using:
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket listener;
public Server(int port) throws IOException {
listener = new ServerSocket(port);
}
public void run() {
while(true) {
try {
Socket server = listener.accept();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("What is your name?");
DataInputStream in = new DataInputStream(server.getInputStream());
String user_name = in.readUTF();
out.writeUTF("Hello "+user_name);
while(true) {
String client_message = in.readUTF();
out.writeUTF(client_message);
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int port = 6006;
try {
Thread t = new Server(port);
t.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Can someone explain what I'm doing wrong?
I have looked at the using Runnable instead of Extends Thread, but I ran into even more problems there, so I want to try and work with this first.
Incoming connections are only handled by the line listener.accept();. But after you got a client connected, you're stuck in the while loop. You need to create a new Thread (or Runnable executed on an ExecutorService if you expect high load), and start it, then immediately accept the next connection.
In a nutshell, this is what is going wrong.
You are using exactly ONE thread as the server.
Blocking this thread when you call listener.accept()
This is what you need to do:
Create two classes
1: Server - Similar to what you have now, but instead of doing the actual work of acting as an echo server, it just spawns a new Thread which starts listening on a NEW PORT (which you can select randomly), and sends the client the address for this new port. The client will then get the new port number and would try to connect to the server on the new port.
2: The Echo thread - This starts a new listener on the port passed, and does the job of echoing to whoever is listening.
OR:
You start a UDP server rather than a TCP server, and all this will not matter then, but that is out of the purview of this specific question.

Sending RDF/XML using Sesame or Apache Jena with Sockets

I am trying to send RDF/XML from a Client to a Server using sockets in Java. When I send the information the Server program hangs and does not receive the info unless I close the Socket or OutputStream on the Client side. Even if I flush the OutputStream on the Client-side the Server does not receive the data unless I close the Socket/Stream. I would like to send the information without closing the socket. Here is some example code for the Client (using Sesame):
import java.io.*;
import java.net.*;
import org.openrdf.rio.*;
import org.openrdf.rio.helpers.*;
import org.openrdf.model.URI;
import org.openrdf.model.Model;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.Statement;
import org.openrdf.model.impl.*;
import org.openrdf.model.vocabulary.*;
public class SimpleRDFClient {
private Socket socket = null;
public static void main(String[] args) {
new SimpleRDFClient(args[0],Integer.parseInt(args[1])).launch();
}
public SimpleRDFClient(String host, int port) {
try {
socket = new Socket(host,port);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void launch() {
try {
OutputStream out = socket.getOutputStream();
BufferedOutputStream dos = new BufferedOutputStream(out);
Model model = new LinkedHashModel();
ValueFactory factory = new ValueFactoryImpl();
URI clive = factory.createURI("http://www.site.org/cliveAnderson");
Statement st = factory.createStatement(clive, RDF.TYPE, FOAF.PERSON);
model.add(st);
Rio.write(model,dos,RDFFormat.RDFXML);
dos.flush();
//Some other stuff
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
And the Server Handler:
import java.io.*;
import java.net.*;
import org.openrdf.rio.*;
import org.openrdf.rio.helpers.*;
import org.openrdf.model.*;
import org.openrdf.model.impl.*;
public class SimpleRDFSHandler implements Handler {
public void handleConnection(Socket socket) {
Model model = null;
try {
InputStream in = socket.getInputStream();
model = Rio.parse(in,"www.blah.com",RDFFormat.RDFXML);
for (Statement st: model) {
System.out.println(st);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
The problem seems to come from the Rio.parse() method hanging (I think because it does not know when the input ends). I get a similar problem when I use the Jena api in a similar way, i.e. using Model.write(outputstream,format) and Model.read(inputstream,format) instead of Rio. I have looked at the source and the javadoc for ages but can't solve the problem. I think it must be something simple I have misunderstood. Any ideas?
I don't think this is in any way a Jena/Sesame specific issue but rather a Java issue around your use of sockets. Is there actually a practical reason you want to not close the socket?
I don't see why this would ever be advisable unless you want to continuously post data and process it as it is received on the server side? If this is the case both Jena and Sesame have APIs that specifically allow you to control what happens to data as it parsed in so that you aren't reliant on your read calls from completing before you process the data.
Also why use sockets, both Sesame and Jena have comprehensive HTTP integration which is much easier to use and deploy than rolling your own socket based server and clients.
The Ugly Hacky Solution
If you really must do this then there is a workaround but it is somewhat horrid and fragile and I would strongly recommend that you do not do this.
On the client side after you write the data write a sequence of bytes that indicate end of stream. On the server side wrap the socket stream with a custom InputStream implementation that recognizes this sequence and stops returning data when it is seen. This should allow the Jena/Sesame code which is expecting the stream to finish to function correctly.
The sequence of bytes need to be carefully chosen such that it won't naturally occur in the data.
To be honest this is a terrible idea, if your aim is to continuously post data this won't really solve your problem because then you'll just be leaking sockets server side unless you put the server side socket handling code in a while (true) loop which is likely another bad idea.

My server stops working when reading .accept(), using Sockets

please excuse my writing errors...
I'm using NetBeans to run a homemade server and a client, and it all works fine. As I said before, I'm using "Socket" on my client, and "ServerSocket" on my sv. I'm also using JDBC Mysql in the server.
The problem starts when I generate both java files in their distributable folders and use them. The client sends information to the server (it starts with .getOutputStream() and .getInputStream(), then .flush() ), but the server doesn't receive any message. I tried seeing where it stops and it's in
clients[i] = new Client (server.accept(), i);
The crazy thing happens when I try executing my server from NetBeans and the client from my desktop... It works! So the server must be the problem. I'm also using an opened UDP port, and i'm looking for the IP of the server on 192.168.0.10 (which is my computer, in LAN).
I hope someone can help me, thanks in advance!
Here I paste my code, i'm sorry some variables are in spanish:
public ServidorMultiCliente() {
super("Servidor MultiCliente");
initComponents();
try{
servidor = new ServerSocket( 500, maxNumberClients);
}catch(IOException excepcion){
excepcion.printStackTrace();
System.exit(1);
}
serverWriteBox.append("Server iniciated, waiting for connections..."); }
I run these, from the Server:
public void ejecutar(){
clientsAcceptor.start();
messagesListener.start(); }
Where clientsAcceptor is:
private class aceptadorClientes extends Thread{
public void run(){
for( int i = 1; i < maxNumberClients; i++ ){
try{
clientes[i] = new Cliente (servidor.accept(), i); // **Here it stops**
// It never reaches here... (without using NetBeans)
clientes[i].start();
clientes[i].aceptado = true;
}catch(IOException excepcion){
excepcion.printStackTrace();
}
}
That's how I accept clients in different threads. I make the same thing with messageListener, which is a new thread for every new client. It's in a loop, always listening. And here I paste my executable Client, which is different from the Cliente class I was using in ServidorMultiCliente:
public Cliente(){
}
public Cliente(String host){
this.host = host;
this.executeConnection();
}
public void executeConnection(){
int connect = 0;
try {
cliente = new Socket(InetAddress.getByName(host), 500);
conectar = 1;
} catch (IOException ex) {
conectar = 0;
this.ejecutarConexion();
}
if(conectar == 1){
obtainFlows();
}
}
private void obtainFlows(){
try{
output= new ObjectOutputStream( cliente.getOutputStream());
output.flush(); // Here I should be "connected"
input = new ObjectInputStream(cliente.getInputStream());
} catch(IOException ex){
this.initiateDisconnection();
}
sendFlows("I'm connected!");
new messageListener().start(); // This is a thread
}
ServerSocket#accept is a blocking call. It listens to a port and returns a Socket when a client connects. You don't show very much of your server logic but it seems you put clients in an array so you obviously want to support more than one client. You don't show if your Client class starts a thread and returns immediatly.
You should have a server loop that just listens to a server socket and creates clients after it retrieved a client socket. Even if you do this in your Client constructor (I can't tell without the code) it is not a very good place for this and seriously hinders debugging.
If you don't start threads for your clients this would explain a server that "stops" (if "stops" means "blocks" and not "crashes"). See "Writing the Server Side of a Socket" in the Java Tutorial for a detailed explanation.
I can't think of why it behaves different when started via Netbeans. A little bit more of code context is needed.

Categories