I've written a mud (telnet server) in Java.
The client I am using for testing is a simple app that connects to the
mud server on the proper port and displays the decimal values of the
first 30 bytes sent out by the server.
When a connection is received by the server, the first data it sends
are some telnet negotiation data, which happens to be the following in
decimal:
255(IAC) 251(WILL) 91(MXP)
Whenever the server runs in a Windows environment, the telnet client
receives: 255, 251, 91 as it should.
Whenever the server runs in a Linux environment, the telnet client
receives: 195, 191, 195, 187, 91. Only the MXP code (91) is correct.
Does Linux filter out the IAC and WILL at some mysterious level?
I can totally reproduce this. It happens every time. It makes NO
SENSE!
Anyone curious to see this in action can telnet to coffeemud.homeip.net
port 23.
Thanks for any clues,
Bo Zimmerman
> Whenever the server runs in a Linux environment, the telnet client
> receives: 195, 191, 195, 187, 91. Only the MXP code (91) is correct.
>
> Does Linux filter out the IAC and WILL at some mysterious level?
Of course not. I've a number of different telnet clients and
servers under Linux -- they all worked fine.
--
Grant Edwards grante Yow! I don't understand
at the HUMOUR of the THREE
visi.com STOOGES!!
> I can totally reproduce this. It happens every time. It makes NO
> SENSE!
>
If you can reproduce it, it have to make sense. In contrary, it's hard to
track down bugs that do not happen every time.
--
Jan
Might it be translating the codes into UTF-8 or something? Just a
thought. What function are you using to read the data?
Also, have you tried this with multiple Java implementations?
Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
What does the code for sending this look like?
Sounds like at some point a conversion from
iso-8859-1 to utf-8 happens.
--
Kasper Dupont
Something is interpreting your data as iso-8859-1 encoded characters
and converting them to utf-8. How are you sending this data? Make
sure it is NEVER seen as a Java String. Only use byte[] arrays for
special data, and you should be safe. Also remember to escape
anything that might otherwise be mistaken for a telnet command.
--
Måns Rullgård
m...@inprovide.com
out = new PrintWriter(sock.getOutputStream());
in = new BufferedReader(new
InputStreamReader(sock.getInputStream()));
char[] mxpWill={TELNET_IAC,TELNET_WILL,TELNET_MXP};
out.write(mxpWill);
out.flush();
out.println("");
out.flush();
I'm no java expert, so it is not obvious to me
from above code if it should work or not. What
is important here is, that the data you send
must be treated as binary data, not text. You
should take a look on Måns' reply, which
suggests you use byte[] instead of char[]. BTW
where are all those TELNET_* macros defined?
--
Kasper Dupont
You should send a bare byte array to the socket,
the char array makes Java assume you're sending
text and converts the Unicode characters used
internally in Java into an external character
set (ISO-8859-1?).
--
Tauno Voipio
tauno voipio (at) iki fi
The OP's data is being converted from iso-8859-1 to utf-8. Most
likely, his distribution uses utf-8 as the default character
encoding.
--
Måns Rullgård
m...@inprovide.com
First the writer.. notice it's been a bit "re-done" to reflect replies:
public static final int TELNET_MXP=91;
public static final int TELNET_SE=240;
public static final int TELNET_WILL=251;
public static final int TELNET_WONT=252;
public static final int TELNET_DO=253;
public static final int TELNET_DONT=254;
public static final int TELNET_IAC=255;
OutputStream raw=sock.getOutputStream();
raw.write(TELNET_IAC);
raw.write(TELNET_WILL);
raw.write(TELNET_MXP);
raw.flush();
out = new PrintWriter(new
OutputStreamWriter(sock.getOutputStream(),"iso-8859-1"));
in = new BufferedReader(new
InputStreamReader(sock.getInputStream(),"iso-8859-1"));
....
proceeds from here on out with out.printlns and so forth...
* And now for the reader:
// first the linux box
try{
Socket S=new Socket("192.168.1.103",23);
BufferedReader in=new BufferedReader(new
InputStreamReader(S.getInputStream()));
PrintWriter out=new PrintWriter(S.getOutputStream());
S.setSoTimeout(5000);
for(int i=0;i<30;i++)
{
int c=in.read();
System.out.print("("+((int)c)+") ");
}
}
catch(Exception e){}
// next the windows box
System.out.print("\n\r\n\r-----------------101-5555:");
try{
Socket S=new Socket("192.168.1.101",5555);
BufferedReader in=new BufferedReader(new
InputStreamReader(S.getInputStream()));
PrintWriter out=new PrintWriter(S.getOutputStream());
S.setSoTimeout(5000);
for(int i=0;i<30;i++)
{
int c=in.read();
System.out.print("("+((int)c)+") ");
}
}
catch(Exception e){}
** Now the output:
I run two of the servers, one of the Windows box, one on the Linux box.
When running my reader from the Windows box, BOTH client checks return:
255, 251, 91... as it should.
When running my reader from the Linux box, BOTH client checks return:
91... skipping the 255, 251 altogether.
The important part, however, is that my professional client ZMUD from
ZuggSoft, which never had any problems receiving and replying to those
telnet codes when I was running the server on the Windows Box (and
still has no trouble with the Windows server), now just spits out
graphics characters at the intro.. apparantly not receiving the proper
values.
I'm about to give up. :( Any help is appreciated.
- Bo
Have you deactivated the (x)inetd telnet service and run your application
standalone, or do you use (x)inetd? AFAIK the latter case does some
mangling on the data.
--
Jan
> Here is the relevant code.
>
> First the writer.. notice it's been a bit "re-done" to reflect replies:
>
> public static final int TELNET_MXP=91;
> public static final int TELNET_SE=240;
> public static final int TELNET_WILL=251;
> public static final int TELNET_WONT=252;
> public static final int TELNET_DO=253;
> public static final int TELNET_DONT=254;
> public static final int TELNET_IAC=255;
>
> OutputStream raw=sock.getOutputStream();
> raw.write(TELNET_IAC);
> raw.write(TELNET_WILL);
> raw.write(TELNET_MXP);
> raw.flush();
This should work.
> out = new PrintWriter(new
> OutputStreamWriter(sock.getOutputStream(),"iso-8859-1"));
> in = new BufferedReader(new
> InputStreamReader(sock.getInputStream(),"iso-8859-1"));
Hard-coding a character encoding is generally a bad idea, though this
one is not the cause of your problem.
> proceeds from here on out with out.printlns and so forth...
>
> * And now for the reader:
>
> // first the linux box
> try{
> Socket S=new Socket("192.168.1.103",23);
> BufferedReader in=new BufferedReader(new
> InputStreamReader(S.getInputStream()));
The InputStreamReader is the problem.
> PrintWriter out=new PrintWriter(S.getOutputStream());
>
> S.setSoTimeout(5000);
> for(int i=0;i<30;i++)
> {
> int c=in.read();
> System.out.print("("+((int)c)+") ");
> }
> }
> catch(Exception e){}
>
> ** Now the output:
> I run two of the servers, one of the Windows box, one on the Linux box.
> When running my reader from the Windows box, BOTH client checks return:
> 255, 251, 91... as it should.
> When running my reader from the Linux box, BOTH client checks return:
> 91... skipping the 255, 251 altogether.
On your Linux machine, the InputStreamReader is interpreting incoming
bytes as utf-8 data, and converting to Java characters. 255 251 is an
illegal utf-8 sequence, and is silently skipped.
On (English) Windows, it appears that iso-8859-1 is used, and one byte
is exactly one character, so all the bytes are legal. If you ran the
client on, for instance, a Japanese Windows version, you'd probably
see similar problems.
When dealing with non-text data in Java, it is important to ensure
that it NEVER, EVER gets stored as a char or String. Use only byte
and byte[] arrays.
--
Måns Rullgård
m...@inprovide.com
If your (x)inetd mangles data, it is badly broken.
--
Måns Rullgård
m...@inprovide.com
--
Jan
> out = new PrintWriter(sock.getOutputStream());
> in = new BufferedReader(new
> InputStreamReader(sock.getInputStream()));
> char[] mxpWill={TELNET_IAC,TELNET_WILL,TELNET_MXP};
> out.write(mxpWill);
> out.flush();
> out.println("");
> out.flush();
If you need the character streams for some reason, you could try this:
outS = sock.getOutputStream();
out = new PrintWriter(outS);
inS = sock.getInputStream();
in = new BufferedReader(new InputStreamReader(inS));
byte[] mxpWill = {TELNET_IAC, TELNET_WILL, TELNET_MXP};
outS.write(mxpWill);
outS.flush();
I don't offer any guarantees... but trying that wouldn't hurt, would it?
--
Timo Voipio | Helsinki, Finland | ICBM at: 60 11.800 N 024 52.760 E
GeekCode ver 3: GU>CC d s-: a--- C++ UL(+)$>+++$ P+>+++ L++(+) E- W++ N++
o? K? w O M- V- PS PE Y+ PGP+ t 5++ X R tv- b++(++++) DI+ D G e- h! r !y
Remove +newsharvested to e-mail me | Poista +newsharvested jos meilaat