显示标签为“socket”的博文。显示所有博文
显示标签为“socket”的博文。显示所有博文

2008年7月23日星期三

我发现我爱上nio了

Java从1.4版本以后提供的新特性:nio我以前一直没用过。写网络程序时一直喜欢用Socket+Stream的阻塞IO。但是这回接的任务要求很高并发和性能的网络交互处理……用原来的阻塞IO肯定不行(总不能一个链接就用一个专用线程处理吧……就是用线程池也架不住好几千的线程一起运行吧= =||,所以用了一下nio的非阻塞io模型,起初发现nio很麻烦,什么事情都要求手动同步,并且很容易出bug...经常是出了bug都不知道从哪里下手(因为程序逻辑和同步顺序的原因)……而且经常出现调用某个函数,必须使用某个特定 的线程的情况,处理异常不得不使用大量的回掉函数……
总之,吧某熊搞的是精疲力竭的……
不过自打用上了Mina,情况改变了(怎么感觉像托儿= =||)。Mian吧nio进行了包装,并对网络IO处理进行了分层处理,采用了事件化的io模型。感觉就和用vb的winsock控件一样,而且比winsock的要简单且功能丰富。再也不用为了大量的同步,回掉和异常处理而操心了,oh,yeah~
Mian是apache的开源项目,网站是http://mina.apache.org 有兴趣的不妨看看~

2008年7月6日星期日

某人的作业,有用的拿走

今天下午五分钟给某人赶制的作业一份,有需要的拿走。
关键字:java socket tcp 文件传输


import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.Socket;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;

/*
* Copyrights (C) 2008 Bearice (Bearice@Gmail.com)
* Release under GNU/GPL Version 2.
*/
/**
*
* @author Bearice
*/
public class FileTransport {

public static void send(String args[]) throws Exception {
String host = args[1];
int port = Integer.parseInt(args[2]);
System.out.printf("Connecting to %s:%d\n", host, port);
Socket socket = SocketFactory.getDefault().createSocket(host, port);
FileInputStream fis = new FileInputStream(args[3]);
int b;
System.out.println("Sending...");
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
while ((b = fis.read()) != -1) {
bos.write(b);
}
bos.close();
}

public static void recv(String args[]) throws Exception {
int port = Integer.parseInt(args[1]);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(args[2]));
System.out.printf("Listening on port %d\n", port);
Socket socket = ServerSocketFactory.getDefault().createServerSocket(port).accept();
int b;
InputStream is = socket.getInputStream();
System.out.println("Recving...");
while ((b = is.read()) != -1) {
bos.write(b);
}
bos.close();
}

public static void main(String[] args) throws Exception {
if (args.length == 4 && args[0].equalsIgnoreCase("send")) {
send(args);
} else if (args.length == 3 && args[0].equalsIgnoreCase("recv")) {
recv(args);
} else {
System.out.println("Usage:");
System.out.println("FileTransport [recv|send <host>] <port> <file>");
}
}
}

2008年7月3日星期四

Java在处理SSL时证书无效的问题,以及解决方法

Java内置了对HTTPS和SSL的支持,但是我在写客户端时遇到了一些问题,比如最大的问题就是在连接的服务器没有一个有效的(也就是经过根CA认证的)SSL证书时会报错。Google了一下,说有两种方式:一种是事先把目标证书导入Java的证书管理器里,另一种是强制忽略证书合法性检查。第一种方法不用对代码进行什么更改,只要运行一个命令就行了,但是缺点是每次服务器更换证书都要进行一次导入。
第二种方法需要更改一下代码,优点是可以应用于任何SSL证书,而且不用重复导入,缺点也很明显,降低了系统的安全性。
下面是第二钟方法的实例代码


try {
final SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {

public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
//这里进行有效性检查,不抛出异常就算检查成功
}

public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}, null);
sleep(100);
SSLSocketFactory factory = sslContext.getSocketFactory();
final SSLSocket socket = (SSLSocket) factory.createSocket("127.0.0.1", 4433);
SSLSession session = socket.getSession();
X509Certificate cert = null;
try {
cert = (X509Certificate) session.getPeerCertificates()[0];
} catch (SSLPeerUnverifiedException e) {
e.printStackTrace();
System.err.println(session.getPeerHost() + " did not present a valid certificate");
return;
}
System.out.println(session.getPeerHost() + " has presented a certificate belonging to" + "[" + cert.getSubjectDN() + "]\n" + "The certificate was issued by: \t" + "[" + cert.getIssuerDN() + "]");
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println("GET /index.html HTTP/1.0");
pw.println("Server: mail.google.com");
pw.println("Connection: close");
pw.println();
pw.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String ln;
while ((ln = in.readLine()) != null) {
System.err.println(ln);
}
} catch (Exception ex) {
Logger.getLogger(ServerLauncher.class.getName()).log(Level.SEVERE, null, ex);
}