最近做的一个项目中,涉及到socket通信部分很多。在查阅大量资料后发现资料对于我自己大多分两种,过于理论或者代码深度太深看不懂。总觉得缺少中间桥梁让我平缓的过度。在观看郭霖大哥(我要给你生猴子)的视频讲解后恍然大悟,将讲解实例代码敲了下来并适当做了注解。
关于socket的基础知识网上很多很详细,我就不做过多的讲解,直接上代码。
客户端:
package socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class Clientsocket {
public static void main(String[]args){
Clientsocket client=new Clientsocket();
client.start();
}
public void start(){
BufferedReader reader=null;
BufferedReader read=null;
BufferedWriter writer=null;
Socket socket=null;
try {
reader=new BufferedReader(new InputStreamReader(System.in));
String outputstring;
socket=new Socket("127.0.0.1", 9898);
read=new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
startServerListener(read);
while(!(outputstring=reader.readLine()).equals("bye")){
writer.write(outputstring+"\n");
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
read.close();
writer.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*
* 监听功能,新开一个线程不影响主线程的运行,是客户端能实时监听来自服务器的数据
*/
public void startServerListener(final BufferedReader reader){
new Thread(new Runnable() {
@Override
public void run() {
try {
String response;
while((response=reader.readLine())!=null){
System.out.println(response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
服务器:
package SeeHtml;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
public class Server {
BufferedWriter writer=null;
BufferedReader reader=null;
public static void main(String[]args){
Server serversocket=new Server();
serversocket.start();
}
public void start(){
ServerSocket server=null;
Socket socket=null;
try {
server=new ServerSocket(9898);
while(true){
socket=server.accept();
/*
* 当没有客户端连接服务器时,accept方法会阻塞住
*/
System.out.println("client "+socket.hashCode()+"connect...");
manageConnection(socket);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
socket.close();
server.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
/*
* 连接管理
* 每次客户端连接服务器是时都会生成一个socket,将socket传入manage进行处理和发送
*/
public void manageConnection(final Socket socket){
new Thread(new Runnable(){
public void run(){
String string=null;
try {
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
/*
* 下面为测试代码,为了测试客户端的监听功能(客户端接受服务器主动发送数据)是否成功,定时发送心跳包
* 由于在匿名类中使用,writer需要设置为static或者全局变量
* new Timer().schedule(new TimerTask(){
public void run(){
try {
writer.write("heart once...\n");
writer.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},3000, 3000);
*/
/*
* 注意:主线程中需要加入while形成循环,否子运行一次就会推出接受客户端信息
* 同理,客户端在写消息的时候也需要注意这一点
*/
while(!(string=reader.readLine()).equals("bye")){
System.out.println("client "+socket.hashCode()+":"+string);
writer.write(string+"\n");
writer.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
writer.close();
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
}
服务器跟客户端的代码中使用了很多循环和阻塞,为的是防止出现一端已经断开连接,另一端缺继续写入数据这种情况引发错误。
正如我上面所说,我们的代码使用了很多阻塞循环和线程,使得在真正使用时会出现运行效率低,使用不方便等问题。但是java官方也考虑到此问题,在jdk1.4之后推出了java.nio。随后有人对此又进行了封装,得到了不少好用的框架,比如mina,可以学一学。
在此附上郭霖大哥的课程教学连接:
点击打开链接http://www.imooc.com/learn/223