I created custom Twitch bot with using of cavariux library. I called this methods in main class.
bot.setOauth_Key("oauth:key_Value");
bot.connect();
bot.joinChannel(channel.toString());
bot.start();
Approximately one of the 5-6 launches of the bot is accompanied by an exception
java.net.SocketException: Connection reset by peer
. The stack trace indicates that the exception starts on this line.
while ((line = this.reader.readLine( )) != null && !stopped)
in TwitchBot class in method start(). I didn't change code of this library except adding utf encoding in method connect(String ip, int port).
this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
I've tested my bot on different PCs. On some machines I don't have this issue. On some I got this exception more often.
This is code of method start() in TwitchBot class.
public final void start()
{
if (isRunning()) return;
String line = "";
stopped = false;
try {
while ((line = this.reader.readLine( )) != null && !stopped) {
if (line.toLowerCase( ).startsWith("ping")) {
LOGGER.log(Level.INFO,"> PING");
LOGGER.log(Level.INFO,"< PONG " + line.substring(5));
this.writer.write("PONG " + line.substring(5) + "\r\n");
this.writer.flush();
} else if (line.contains("PRIVMSG"))
{
String str[];
str = line.split("!");
final User msg_user = User.getUser(str[0].substring(1, str[0].length()));
str = line.split(" ");
Channel msg_channel;
msg_channel = Channel.getChannel(str[2], this);
String msg_msg = line.substring((str[0].length() + str[1].length() + str[2].length() + 4), line.length());
LOGGER.log(Level.INFO,"> " + msg_channel + " | " + msg_user + " >> " + msg_msg);
if (msg_msg.startsWith(commandTrigger))
onCommand(msg_user, msg_channel, msg_msg.substring(1));
if (msg_user.toString().equals("jtv") && msg_msg.contains("now hosting")) {
String hoster = msg_msg.split(" ")[0];
onHost(User.getUser(hoster), msg_channel);
}
onMessage(msg_user, msg_channel, msg_msg);
} else if (line.contains(" JOIN ")) {
String[] p = line.split(" ");
String[] pd = line.split("!");
if (p[1].equals("JOIN"))
userJoins(User.getUser(pd[0].substring(1)), Channel.getChannel(p[2], this));
} else if (line.contains(" PART ")) {
String[] p = line.split(" ");
String[] pd = line.split("!");
if (p[1].equals("PART"))
userParts(User.getUser(pd[0].substring(1)), Channel.getChannel(p[2], this));
} else if (line.contains(" WHISPER ")) {
String[] parts = line.split(":");
final User wsp_user = User.getUser(parts[1].split("!")[0]);
String message = parts[2];
onWhisper(wsp_user, message);
} else if (line.startsWith(":tmi.twitch.tv ROOMSTATE")) {
} else if (line.startsWith(":tmi.twitch.tv NOTICE"))
{
String[] parts = line.split(" ");
if (line.contains("This room is now in slow mode. You may send messages every"))
{
LOGGER.log(Level.INFO,"> Chat is now in slow mode. You can send messages every " + parts[15] + " sec(s)!");
} else if (line.contains("subscribers-only mode")) {
if (line.contains("This room is no longer"))
LOGGER.log(Level.INFO,"> The room is no longer Subscribers Only!");
else
LOGGER.log(Level.INFO,"> The room has been set to Subscribers Only!");
} else {
LOGGER.log(Level.INFO,line);
}
} else if (line.startsWith(":jtv MODE "))
{
String[] p = line.split(" ");
if (p[3].equals("+o")) {
LOGGER.log(Level.INFO,"> +o " + p[4]);
} else {
LOGGER.log(Level.INFO,"> -o " + p[4]);
}
} else if (line.toLowerCase().contains("disconnected"))
{
LOGGER.log(Level.INFO, line);
this.connect();
} else
{
LOGGER.log(Level.INFO,"> " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
This is code of method connect() in TwitchBot class.
public void connect(String ip, int port)
{
if (isRunning()) return;
try{
if (user == null || user == "")
{
LOGGER.log(Level.SEVERE, "Please select a valid Username");
System.exit(1);
return;
}
if (oauth_key == null || oauth_key == "")
{
LOGGER.log(Level.SEVERE,"Please select a valid Oauth_Key");
System.exit(2);
return;
}
#SuppressWarnings("resource")
Socket socket = new Socket(ip, port);
this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),StandardCharsets.UTF_8));
this.writer.write("PASS " + oauth_key + "\r\n");
this.writer.write("NICK " + user + "\r\n");
this.writer.write("USER " + this.getVersion() + " \r\n");
this.writer.write("CAP REQ :twitch.tv/commands \r\n");
this.writer.write("CAP REQ :twitch.tv/membership \r\n");
this.writer.flush();
String line = "";
while ((line = this.reader.readLine()) != null)
{
if (line.indexOf("004") >= 0) {
LOGGER.log(Level.INFO,"Connected >> " + user + " ~ irc.twitch.tv");
break;
}else {
LOGGER.log(Level.INFO,line);
}
}
} catch (IOException e)
{
e.printStackTrace();
}
}
Thank you for the help
This error means that the peer (i.e. the Twitch server) closes abruptly your connection. See this answer for more details.
I don't know if you can do something to fix that because it can have various external origins (peer crash...). Maybe you can wait and try to reconnect later (note that you might be blacklisted if you connect too often).
Related
I am facing a problem in Java jsch. I have opened a Shell channel and I have a list of commands that I want to execute and read from the shell.
But in that commands list, there's one command that needs to be scrolled down in the shell to be shown until its end.
I am strugling to implement this auto-scroller for that command.
In my code What I did:
ChannelShell channelShell = (ChannelShell) session.openChannel("shell");
OutputStream inputstream_for_the_channel = channelShell.getOutputStream();
InputStream outputstream_from_the_channel = channelShell.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
PrintStream commander = new PrintStream(inputstream_for_the_channel, true);
channelShell.connect();
if (!commands.get(0).equals("show system information | match \"System Name\"")) {
commands.add(0, "show system information | match \"System Name\"");
}
String readString = "";
String line;
int index = 0;
for (String cmd : commands) {
System.out.println(cmd);
commander.println(cmd);
try {
Thread.sleep(commandsSleep);
} catch (Exception ee) {
}
while ((line = reader.readLine()) != null)
{
if (cmd.equals("admin display-config")) {
commander.println("");
}
GuiApp.textAreaLog.append("\n"+ ++index + " : " + line);
System.out.println(index + " : " + line);
readString += (line+"\n");
}
}
if (routerType.equals("nokia")) {
commander.println("logout");
System.out.println("logout");
try {
Thread.sleep(commandsSleep);
} catch (Exception ee) {
}
} else if (routerType.equals("linux")){
commander.println("exit");
}
commander.close();
channelShell.disconnect();
try {
Thread.sleep(commandsSleep);
} catch (Exception ee) {
}
return readString;
In the part:
while ((line = reader.readLine()) != null)
{
if (cmd.equals("admin display-config")) {
commander.println("");
}
GuiApp.textAreaLog.append("\n"+ ++index + " : " + line);
System.out.println(index + " : " + line);
readString += (line+"\n");
}
Is where I tried to implement a While loop to read the reader until its null, and to add to the commander a printl with "" to try to scroll this problematic command further down.
What I managed to do was to insert a timelimiter to the readbuffer.
for (String cmd : commands) {
GuiApp.textAreaLog.append("\n"+"Running Command : " + cmd);
commander.println(cmd);
System.out.println(cmd);
if (cmd.equals("admin display-config")) {
commandDelay = commandsSleep*10;
}else{
commandDelay = commandsSleep;
}
line = reader.readLine();
while (line!=null)
{
System.out.println(++index + " : " + line);
readString += (line+"\n");
try {
line = timeLimiter.callWithTimeout(reader::readLine, commandsSleep, TimeUnit.MILLISECONDS, true);
} catch (Exception e) {
e.printStackTrace();
break;
}
}
try {
Thread.sleep(commandDelay);
} catch (Exception e) {
//e.printStackTrace();
}
GuiApp.textAreaLog.append("\n"+"Comando executado com sucesso");
}
I am coding client-server multithread calculator using java, socket programming.
There's any syntax error, but msgs cannot be received from server.
I think
receiveString = inFromServer.readLine()
does not works. This code is in Client program, in the while(true) loop.
What is the problem?
Here is my full code.
SERVER
import java.io.*;
import java.net.*;
public class Server implements Runnable
{
static int max = 5; //maximum thread's number
static int i = 0, count = 0; //i for for-loop, count for count number of threads
public static void main(String args[]) throws IOException
{
ServerSocket serverSocket = new ServerSocket(6789); //open new socket
File file = new File("src/serverinfo.dat"); //make data file to save server info.
System.out.println("Maximum 5 users can be supported.\nWaiting...");
for(i=0; i <= max; i++) { new Connection(serverSocket); } //make sockets - loop for max(=5) times
try //server information file writing
{
String dataString = "Max thread = 5\nServer IP = 127.0.0.1\nServer socket = 6789\n";
#SuppressWarnings("resource")
FileWriter dataFile = new FileWriter(file);
dataFile.write(dataString);
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
}
static class Connection extends Thread
{
private ServerSocket serverSocket;
public Connection(ServerSocket serverSock)
{
this.serverSocket = serverSock;
start();
}
public void run()
{
Socket acceptSocket = null;
BufferedReader inFromClient = null;
DataOutputStream msgToClient = null;
String receiveString = null;
String result = "", sys_msg = "";
try
{
while(true)
{
acceptSocket = serverSocket.accept(); // 접속수락 소켓
count++;
inFromClient = new BufferedReader(new InputStreamReader(acceptSocket.getInputStream()));
msgToClient = new DataOutputStream(acceptSocket.getOutputStream());
System.out.println(count + "th client connected: " + acceptSocket.getInetAddress().getHostName() + " " + count + "/" + max);
System.out.println("Waiting response...");
while(true)
{
if (count >= max+1) // if 6th client tries to access
{
System.out.println("Server is too busy. " + max + " clients are already connected. Client access denied.");
sys_msg = "DENIED";
msgToClient.writeBytes(sys_msg);
acceptSocket.close();
count--;
break;
}
try{ msgToClient.writeBytes(result); }
catch(Exception e) {}
try{ receiveString = inFromClient.readLine(); }
catch(Exception e) // if receiveString = null
{
System.out.println("Connection Close");
count--;
break;
}
System.out.println("Input from client : " + receiveString);
try
{
if(receiveString.indexOf("+") != -1) { result = cal("+", receiveString); }
else if(receiveString.indexOf("-") != -1) { result = cal("-", receiveString); }
else if(receiveString.indexOf("/") != -1) { result = cal("/", receiveString); }
else if(receiveString.indexOf("*") != -1) { result = cal("*", receiveString); }
else if(receiveString.indexOf("+") == -1 || receiveString.indexOf("-") == -1 || receiveString.indexOf("*") == -1 || receiveString.indexOf("/") == -1) { result = "No INPUT or Invalid operation"; }
}
catch(Exception e){ result = "Wrong INPUT"; }
try{ msgToClient.writeBytes(result); }
catch(Exception e) {}
}
}
}
catch(IOException e) { e.printStackTrace(); }
}
}
private static String cal(String op, String recv) //function for calculating
{
double digit1, digit2; //first number, second number
String result = null;
digit1 = Integer.parseInt(recv.substring(0, recv.indexOf(op)).trim());
digit2 = Integer.parseInt(recv.substring(recv.indexOf(op)+1, recv.length()).trim());
if(op.equals("+")) { result = digit1 + " + " + digit2 + " = " + (digit1 + digit2); }
else if(op.equals("-")) { result = digit1 + " - " + digit2 + " = " + (digit1 - digit2); }
else if(op.equals("*")) { result = digit1 + " * " + digit2 + " = " + (digit1 * digit2); }
else if(op.equals("/"))
{
if(digit2 == 0){ result = "ERROR OCCURRED: Cannot be divided by ZERO"; }
else{ result = digit1 + " / " + digit2 + " = " + (digit1 / digit2); }
}
return result;
}
#Override
public void run() {
// TODO Auto-generated method stub
}
}
-----------------------------------------------------------------
CLIENT
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) throws IOException
{
Socket clientSocket = null;
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
BufferedReader inFromServer = null;
DataOutputStream msgToServer = null;
String sendString = "", receiveString = "";
try
{
clientSocket = new Socket("127.0.0.1", 6789); //make new clientSocket
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
msgToServer = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Input exit to terminate");
System.out.println("Connection Success... Waiting for permission");
while(true)
{
receiveString = inFromServer.readLine();
if(receiveString.equals("DENIED"))
{
System.out.println("Server is full. Try again later.");
break;
}
else { System.out.println("Connection permitted."); }
System.out.print("Input an expression to calculate(ex. 3+1): ");
sendString = userInput.readLine();
if(sendString.equalsIgnoreCase("exit")) //when user input is "exit" -> terminate
{
clientSocket.close();
System.out.println("Program terminated.");
break;
}
try { msgToServer.writeBytes(sendString); }
catch(Exception e) {}
try { receiveString = userInput.readLine(); }
catch(Exception e) {}
System.out.println("Result: " + receiveString); //print result
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
You've set up your server socket stack wrong.
Your code will make 5 threads, each calling accept on a serversocket.
The idea is to have a single ServerSocket (and not 5, as in your example). Then, this single serversocket (running in a single thread that handles incoming sockets flowing out of this serversocket) will call .accept which will block (freeze the thread) until a connection is made, and will then return a Socket object. You'd then spin off a thread to handle the socket object, and go right back to the accept call. If you want to 'pool' (which is not a bad idea), then disassociate the notion of 'handles connections' from 'extends Thread'. For example, implement Runnable instead. Then pre-create the entire pool (for example, 10 threads), have some code that lets you 'grab a thread' from the pool and 'return a thread' to the pool, and now the serversocket thread will, upon accept returning a socket object, grab a thread from the pool (which will block, thus also blocking any incoming clients, if every thread in the pool is already taken out and busy handling a connection), until a thread returns to the pool. Alternatively, the serversocket code checks if the pool is completely drained and if so, will put on a final thread the job of responding to that client 'no can do, we are full right now'.
I'm not sure if you actually want that; just.. make 1 thread per incoming socket is a lot simpler. I wouldn't dive into pool concepts until you really need them, and if you do, I'd look for libraries that help manage them. I think further advice on that goes beyond the scope of this question, so I'll leave the first paragraph as an outlay of how ServerSocket code ought to work, for context.
I would like to that when the server gets a message from the client and the message is for example "start", server sends back ips and ports of the rest of clients.
Part of the server:
...
for (i = 0; i < max_clients; i++) {
sd = client_socket[i];
memset(buffer, 0, 10000);
if (FD_ISSET( sd , &readfds)) {
if ((valread = read( sd , buffer, 1024)) == 0) {
getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" ,
inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
close( sd );
client_socket[i] = 0;
}
else {
char cmd[10] = "";
int k;
for(k=0; k<strlen(buffer)-1; k++) {
char tmp[2] = "";
tmp[0] = buffer[k];
strcat(cmd, tmp);
}
if (strcmp(cmd, "start") == 0) {
char clientInfo[1000] = "[ ";
for(j=0; j<max_clients; j++) {
if (client_socket[j] > 0 && client_socket[j] != sd) {
char port[12];
sprintf(port, "%d", clients[j].port);
strcat(clientInfo, "{");
strcat(clientInfo, clients[j].addr);
strcat(clientInfo, " - ");
strcat(clientInfo, port);
strcat(clientInfo, "} ");
}
}
strcat(clientInfo, "]");
send(sd, clientInfo, strlen(clientInfo), 0);
printf("%s\n", clientInfo);
} else {
buffer[valread] = '\0';
for(j=0; j<max_clients; j++) {
int outSock = client_socket[j];
if(outSock != master_socket && outSock != sd) {
send(outSock , buffer , strlen(buffer) , 0 );
}
}
}
}
}
}
...
Part of the client:
public ChatWindowController() {
try {
clientSocket = new Socket("127.0.0.1", 54000);
outToServer = new DataOutputStream(clientSocket.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
thread = new Thread() {
#Override
public void run() {
try {
while(isRunning) {
if (ta_display != null) {
String message = inFromServer.readLine();
System.out.println(message);
ta_display.appendText(message + '\n');
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
};
thread.start();
} catch(Exception e) {
e.printStackTrace();
}
}
...
...
#FXML
void sendMsg(ActionEvent event) {
String message = tf_user_input.getText();
if (username == null || username.equals("") || username.trim().equals("")) {
ta_display.appendText("You can not send a message, set your username!\n");
return;
}
if (message != null && !message.equals("") && !message.trim().equals("")) {
try {
out.println(username + ": " +message);
out.flush();
} catch(Exception e) {
e.printStackTrace();
}
ta_display.appendText(username + ": " + message + "\n");
}
tf_user_input.setText("");
}
#FXML
void sendFile(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
out.println("start");
out.flush();
}
Messages from clients are sent to the server, and the server sends them to other clients, it works.
But when client send message "start" to the server I want to send back ips and ports of the rest of the clients, but it doesn't arrive to the client back, only when one of the other clients writes something, a message with ip and user ports comes.
E.g. "[{127.0.0.1 - 1234} {127.0.0.1}]User: example"
Like the message has been lost and arrived with another. I print the ips and ports to see if everything is alright and it prints corectly.
I'm not getting any errors.
Does anybody know how to send back a message after specific message from client?
When I try to get information from a Socket (it's at localhost) it never returns what I want (info from my server) with php it works fine..
Java application: run & debug doesn't return anything
Glassfish server: run doesn't return anything, debug return all the info, everytime i debug
PHP Code:
$Socket = fsockopen($this->Host, $this->Port, $errno, $errstr, 5);
if(!$Socket) {
return false;
} else {
stream_set_timeout($Socket, 1);
stream_set_blocking($Socket, false);
fwrite($Socket, chr(6).chr(0).chr(255).chr(255).'info');
while(!feof($Socket)) {
$this->SocketData .= fgets($Socket, 8192);
}
fclose($Socket);
return true;
}
Java Code:
public static String serverInfo(String ip, Integer port) {
try (Socket socket = new Socket(ip, port)) {
//System.out.println("Connected to " + socket.getInetAddress() + " on port " + socket.getPort() + " from port " + socket.getLocalPort() + " of " + socket.getLocalAddress());
OutputStream os = socket.getOutputStream();
String info = ((char) 6 + "" + (char) 0 + "" + (char) 255 + "" + (char) 255 + "info");
System.out.println(info);
os.write(info.getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder stb = new StringBuilder();
while (br.ready()) {
stb.append(br.readLine());
}
if (!stb.toString().isEmpty()) {
//System.out.println("Info: " + stb.toString());
return stb.toString();
} else {
//System.out.println("No answer from server.");
return null;
}
} catch (UnknownHostException e) {
System.err.println("I can't find " + ip);
} catch (SocketException e) {
System.err.println("Could not connect to " + ip);
} catch (IOException e) {
System.err.println(e);
}
return null;
}
What I was looking for, was to do the same as php does, connect to the socket, get the information and return/save/whatever with that information and I don't know what happens that only 1/100 times that I try, it returns something.
When I run in my web application AND debug, it returns EVERYTIME the info, something is really wrong and I can't figure it out..
PS: It's meant to get OTServer information.
I think this is not the right way to read from the br.
while (br.ready()) {
stb.append(br.readLine());
}
Try changing this to:
String line = null;
while ((line = br.readLine()) != null) {
stb.append(line);
}
Also, call os.close() after this line.
os.write(info.getBytes());
I'm having some issues with a while loop. This while loop is run in a thread, and is the "main loop" of the thread, and I'm having issues with it not continuing if one of the if statements it loops over is false. This thread handles both sending and receiving IRC Commands/Messages for use in a minecraft client.
The code as it stands is below:
do {
System.out.println("IRC Thread Looped!");
if(tosend != "") {
writer.write("PRIVMSG " + channel + " :"+tosend+"\r\n");
System.out.println(tosend);
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] \2477"+nick+": \247f"+tosend);
tosend = "";
writer.flush();
}
if((line = reader.readLine()) != null) {
if(line.startsWith("PING ")) {
writer.write("PONG " + line.substring(5) + "\r\n");
writer.flush( );
}
else {
// we need to pretty this ugly sh*t up!
try {
String parsedline;
String args[] = line.split("!");
String args2[] = args[1].split(":");
args[0] = args[0].substring(1, args[0].length());
parsedline = "\2477"+ args[0] +": \247f"+ args2[1];
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] "+parsedline);
}
catch(Exception e) {
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f]\247f "+line);
continue;
}
}
}
try {
Thread.sleep(90L);}catch(Exception e) { };
}
} while(true);
Note that java threads like to eat exceptions that get thrown out of the run() method.
Since you have IO such as if((line = reader.readLine()) != null){ not in a try/catch, you might be throwing an exception and exiting.
What I like to do with threads is to put the main thread code in runImpl() and have the run() look like this.
public void run()
{
try
{
runImpl();
}
catch( Throwable t )
{
// log the throwable
}
}
Then at a minimum you can discover that your thread threw something unexpected.
If the problem is caused by getLine() blocking behavior you could probably fix it this way. I haven't run that code so I don't guarantee it will work. Also make sure that reader is a BufferedReader.
StringBuilder sb = new StringBuilder();
String line = null;
int n = 0;
do {
System.out.println("IRC Thread Looped!");
if(tosend != ""){
writer.write("PRIVMSG " + channel + " :"+tosend+"\r\n");
System.out.println(tosend);
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] \2477"+nick+": \247f"+tosend);
tosend = "";
writer.flush();
}
while (reader.ready()) {
int c = reader.read();
if (c == -1) {
if (n > 0) {
line = sb.toString();
sb = new StringBuilder();
}
break;
}
if (c == '\n' || c == '\r') {
line = sb.toString();
sb = new StringBuilder();
break;
}
sb.append((char)c);
n++;
}
if(line != null){
if (line.startsWith("PING ")) {
writer.write("PONG " + line.substring(5) + "\r\n");
writer.flush( );
}
else
{
//we need to pretty this ugly shit up!
try{
String parsedline;
String args[] = line.split("!");
String args2[] = args[1].split(":");
args[0] = args[0].substring(1, args[0].length());
parsedline = "\2477"+args[0] +": \247f"+ args2[1];
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] "+parsedline);
}catch(Exception e){
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f]\247f "+line);
continue;
}
}
line = null;
n = 0;
}
try{Thread.sleep(90L);}catch(Exception e){};
} while(true);