Java实现msn发消息的功能

说明:以下是实现代码,关于msn协议的分析请参考http://www.cnpaf.net/Forum/viewthread.php?tid=1761。
这里只考虑了如何实现msn发消息的功能,至于面向对象,线程之类的暂时没考虑那么多,大家就将就一下了。。。
1.主类:
/**
* Author EvilgoD
* QQ:7771465
* blog:http://evilgod.iteye.com
* Date 2008-1-8
*/
public class MyMSN{

public static void main(String []args) throws Exception {
String username="urname@xxx.com";
String password="urpsw";
String remoteusername="urfriend@xxx.com";
String instantmessage="test!";
MSNServer server=new MSNServer(username,password);
server.login();
server.setStatus();
server.send(remoteusername,instantmessage);
server.close();


}
}

2. MSNServer类:
/**
* Author EvilgoD
* QQ:7771465
* blog:http://evilgod.iteye.com
* Date 2008-1-8
*/
import java.io.*;
import java.net.*;
import java.util.*;
import java.security.*;
import javax.net.ssl.*;

public class MSNServer{
public String username,password;
private int command=0;//流水号
private Socket server;
private PrintWriter out;
private MSNFilterStream in;
public String temp;

public MSNServer(String username,String password){
this.username=username;
this.password=password;
}


//登录
public void login() throws Exception{
server = new Socket("messenger.hotmail.com", 1863);
server.setTrafficClass(0x10);
out = new PrintWriter(server.getOutputStream(), true);
in=new MSNFilterStream(new BufferedInputStream(server.getInputStream()));

//报告协议号
message="VER "+command+" MSN10 MSNP9 CVRO ";
out.println(message);
command++;
temp=in.readLine();
System.out.println(temp);

//报告本机消息
message="CVR "+command+" 0x0804 winnt 5.2 i386 MSNMSGR 7.5.0299 MSMSGS "+username+" ";
out.println(message);
command++;
temp=in.readLine();
System.out.println(temp);

//提交登录用户名
message="USR "+command+" TWN I "+username+" ";
out.println(message);
command++;
temp=in.readLine();
System.out.println(temp);

//连接到ns服务器
StringTokenizer st=new StringTokenizer(temp);
st.nextToken();st.nextToken();st.nextToken();
String ns=st.nextToken();//NS地址
out.close();//关闭与DS服务器的连接
in.close();
server.close();
String []split=ns.split(":");
server=new Socket(split[0],Integer.parseInt(split[1]));
server.setTrafficClass(0x10);
out = new PrintWriter(server.getOutputStream(), true);
in=new MSNFilterStream(new BufferedInputStream(server.getInputStream()));
message="VER "+command+" MSN10 MSNP9 CVR0";
command++;
out.println(message);
temp=in.readLine();
System.out.println(temp);

//报告本机信息
message="CVR "+command+" 0x0804 winnt 5.2 i386 MSNMSGR 7.5.0299 MSMSGS "+username+" ";
out.println(message);
command++;
temp=in.readLine();

//发送用户信息
message="USR "+command+" TWN I "+username+" ";
out.println(message);
command++;

//!验证登录信息,首先在HTTPS端口443向nexus.passport.com发送一个GET请求,将账号、密码和NS给定的一长串信息送出
temp=in.readLine();
System.out.println(temp);
st=new StringTokenizer(temp);
st.nextToken();st.nextToken();st.nextToken();st.nextToken();
String args=st.nextToken();
Socket login = new Socket("nexus.passport.com", 443);
login = ((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(login, "nexus.passport.com", 443, true);
BufferedReader readin = new BufferedReader(new InputStreamReader(new LogInputStream(login.getInputStream())));
PrintWriter printout = new PrintWriter(login.getOutputStream(), true);
printout.println("GET /rdr/pprdr.asp");
String host = null;
String get = null;
String data = readin.readLine();
while (data != null) {
System.out.println(data);
if (data.startsWith("PassportURLs:")) {
data = data.substring(14);
StringTokenizer tok = new StringTokenizer(data, ",");
while (tok.hasMoreTokens()) {
String tmp = tok.nextToken();
if (tmp.startsWith("DALogin=")) {
tmp = tmp.substring(8);
host = tmp.substring(0, tmp.indexOf("/"));
get = tmp.substring(tmp.indexOf("/"));
}
}
}
data = readin.readLine();
}
boolean redirect = true;
String auth = null;

//根据情况,会重定向到不同的URL;然后,重新向指定的URL发出请求
while (redirect) {
redirect = false;
login = new Socket(host, 443);
login = ((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(login, host, 443, true);
readin = new BufferedReader(new InputStreamReader(login.getInputStream()));
printout = new PrintWriter(login.getOutputStream(), true);
StringBuffer buf = new StringBuffer();

buf.append("GET ");
buf.append(get);
buf.append(" HTTP/1.1\r\n");
buf.append("Authorization: ");
buf.append("Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=");
try {
buf.append(encode(URLEncoder.encode(username, "UTF-8")));
buf.append(",pwd=");
buf.append(encode(URLEncoder.encode(password, "UTF-8")));
} catch (Exception e) {
e.printStackTrace();
return;
}
buf.append(",");
buf.append(args);
buf.append("\r\nHost: ");
buf.append(host);
buf.append("\r\n");
System.out.println("Get - "+buf.toString());
printout.println(buf.toString());

data = readin.readLine();

while (data != null) {
System.out.println(data);
if (data.startsWith("Location:")) {
redirect = true;
host = data.substring(data.indexOf("://")+3);
get = host.substring(host.indexOf("/"));
host = host.substring(0, host.indexOf("/"));
} else if (data.startsWith("Authentication-Info: ")) {
StringTokenizer tok = new StringTokenizer(data.substring(data.indexOf("da-status=")), ",");
while (tok.hasMoreTokens()) {
data = tok.nextToken();
if (data.startsWith("from-PP=")) {
auth = data.substring(9, data.length()-1);

}
}
}
data = readin.readLine();
}
}

//声明、传递、鉴别用户身份
message="USR "+command+" TWN S "+auth;
System.out.println(message);
out.println(message);
temp=in.readLine();
System.out.println(temp);

}


//设置状态
public void setStatus() throws Exception{
//要求改变状态
message="CHG "+command+" NLN";
out.println(message);
temp=in.readLine();
while(!temp.startsWith("CHL")){
temp=in.readLine();
System.out.println(temp);
}

//客户端回答服务器的验证要求
StringTokenizer st=new StringTokenizer(temp);
st.nextToken();
message="QRY "+command+" msmsgs@msnmsgr.com 32";
out.println(message);
st.nextToken();
String hash=st.nextToken();
String enc = hash+"Q1P7W2E4J9R8U3S5";
MessageDigest digest = MessageDigest.getInstance("MD5");
enc = byteArrayToHexString(digest.digest(enc.getBytes()));
out.print(enc);
out.flush();
temp=in.readLine();
System.out.println("here:"+temp);
}

//发送消息
public boolean send(String remoteusername,String instantmessage) throws Exception{

String rusername=remoteusername;
String imessage=instantmessage;

//询问转接服务器在哪
message="XFR "+command+" SB";
out.println(message);
command++;
temp=in.readLine();
System.out.println(temp);
if(!temp.startsWith("XFR")) return false;

//连接转接服务器
StringTokenizer st=new StringTokenizer(temp);
int cmd=0;
st.nextToken();st.nextToken();st.nextToken();
String []split=st.nextToken().split(":");
Socket swtserver=new Socket(split[0],Integer.parseInt(split[1]));//转接服务器
swtserver.setTrafficClass(0x10);
st.nextToken();
message="USR "+cmd+" "+username+" "+st.nextToken();
cmd++;
System.out.println(message);
PrintWriter swtout=new PrintWriter(swtserver.getOutputStream(),true);
MSNFilterStream swtin=new MSNFilterStream(new BufferedInputStream(swtserver.getInputStream()));
swtout.println(message);
temp=swtin.readLine();
System.out.println(temp);

//发送消息
System.out.println("发送消息");
message="CAL "+cmd+" "+rusername;
cmd++;
swtout.println(message);
System.out.println(message);
temp=swtin.readLine();
System.out.println(temp);
temp=swtin.readLine();
System.out.println(temp);
if(!temp.startsWith("JOI")) return false;
String txt= "MIME-Version: 1.0\r\n";
txt=txt+"Content-Type: text/x-msmsgscontrol\r\n"+"TypingUser: "+username+"\r\n\r\n\r\n";
message="MSG "+cmd+" U"+" "+txt.length()+ "\r\n" + txt;
cmd++;
System.out.println(message);
swtout.print(message);
swtout.flush();


txt = "MIME-Version: 1.0\r\n";
txt = txt+"Content-Type: text/plain; charset=UTF-8\r\n"+
"X-MMS-IM-Format: FN=%E5%AE%8B%E4%BD%93; EF=; CO=0; CS=86; PF=0\r\n\r\n"+imessage;
message="MSG "+cmd+" N"+" "+txt.length()+ "\r\n" + txt;
System.out.println(message);
swtout.print(message);
swtout.flush();

temp=swtin.readLine();
System.out.println(temp);

swtin.close();
swtout.close();
return true;
}

//退出
public void close() throws Exception{
flag=false;
in.close();
out.close();
}


private static String encode(String encodedString) {
String data;
for (int i = 0; i < encodedString.length(); i++) {
if ( encodedString.charAt(i) == '+' ) {
data = encodedString.substring(0, i);
data += "%20" + encodedString.substring(i+1);
encodedString = data;
}
}
return encodedString;
}

private static String byteArrayToHexString (byte[] bytes) {
String hexString = "";

for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
hexString = hexString + byteToHexString(b & 0xf, (b >> 4) & 0xf);
}

return hexString;
}

private static String byteToHexString (int nib1, int nib2) {
char char1, char2;
char1 = nibbleToChar (nib1);
char2 = nibbleToChar (nib2);

char[] chars = new char[2];
chars[0] = char2;
chars[1] = char1;

return (new String (chars));
}

private static char nibbleToChar (int nibble) {
if (nibble < 10) {
return (Integer.toString (nibble)).charAt(0);
} else {
int nib = nibble - 10;
return (char)(((char) nib) + 'a');
}
}
}

3. LogInputStream类
/**
* Author EvilgoD
* QQ:7771465
* blog:http://evilgod.iteye.com
* Date 2008-1-8
*/
import java.io.IOException;
import java.io.InputStream;

class LogInputStream extends InputStream {


private InputStream in;

public LogInputStream(InputStream in) {

this.in = in;

}


public int read() throws IOException {
int value = in.read();
return value;

}


public int available() throws IOException {
return in.available();
}


public int read(byte[] b) throws IOException {

int value = in.read(b);
return value;
}


public int read(byte[] b, int off, int len) throws IOException {
int value = in.read(b, off, len);
return value;
}

public void close() throws IOException {
in.close();
}

}

4. MSNFilterStream类
/**
* Author EvilgoD
* QQ:7771465
* blog:http://evilgod.iteye.com
* Date 2008-1-8
*/
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

class MSNFilterStream extends FilterInputStream{

public MSNFilterStream(InputStream in) {
super(in);
}

public String readLine() throws IOException {
boolean prevReturn = false;
ByteArrayOutputStream b = new ByteArrayOutputStream(128);
while(true) {
int value = this.in.read();
if (value<0)
return "null";
if (value=='\r') {
if (prevReturn) {
b.write('\r');
} else {
prevReturn = true;
}
} else {
if (value == '\n') {
// we are ready, we get \r\n
return new String(b.toByteArray(),"UTF-8");
} else {
prevReturn = false;
b.write(value);
}
}
}

}


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值