第一次接触Socket是大二时的课程设计,当时做的是图书管理系统,源码都是网上下载,考试周拿着代码天天磨,隐约中记得有Socket这么一个单词。
第二次是去年代表学校参加“河北省电子信息职业技能大赛”,接受曹建新师哥的培训。建新师哥当时用手机Android软件做客户端,通过局域网向电脑端服务器传输手机录入的信息。当时我很诧异,客户端是Android平台,服务器是.Net平台,这两种平台是如何在局域网内进行通信的呢?建新师哥的回答是:“通过Socket,把数据打包成JSON格式进行传输。”从此对Socket的认识便有了一种高大上的感觉。
第三次接触是通过马士兵老师的视频,这次瞬间感觉Socket--So Easy。这也验证了米老师的那句话:不怕不知道,就怕不知道。
Socket通信分为服务器Socket即ServerSocket和客户端Socket。
在服务器端,通信前需要建立和客户端的通信通道,建立对客户端通信端口号的监听;在客户端,通信前需要定义进行通信的主机IP和端口号,创建通信通道。两者都准备完毕,下面就可以进行通信了。
服务器端代码:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) {
//创建向客户端传输数据的通道
InputStream in = null;
//创建从客户端接收数据的通道
OutputStream out = null;
try {
//建立和客户端的通信,并定义通信端口
ServerSocket ss = new ServerSocket(5888);
//监听客户端提交的请求
Socket socket = ss.accept();
in = socket.getInputStream();
out = socket.getOutputStream();
//在字节流的基础上进行包装数据流
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
//接收客户端提交的请求
String s = null;
if ((s = dis.readUTF()) != null) {
System.out.println(s);
System.out.println("from:" + socket.getInetAddress());
System.out.println("port:" + socket.getPort());
}
//向客户端传输数据
dos.writeUTF("hi,hello");
dos.close();
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
由于数据流的readUTF()方法和writeUTF()方法都是阻塞式,所以当A向B发送数据后,如果B没有响应,A是无法继续发送数据的,只能傻傻的等待。这个过程好比TCP/IP协议的三次握手,1:A呼叫B,“我是A,收到请回答?”;2:B回应A,“我是B,收到”;3:A继续说,“我想请你吃饭,你有时间吗?”。下面A和B就可以进行通信了。
服务器端代码有了,下面分享客户端代码:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) {
//创建向服务器传输数据的通道
InputStream in = null;
//创建从服务器接收数据的通道
OutputStream out = null;
try {
//定义进行通信的主机IP和端口号
Socket socket = new Socket("localhost", 5888);
in = socket.getInputStream();
out = socket.getOutputStream();
//在字节流的基础上进行包装数据流
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
//向服务器提交数据
dos.writeUTF("hey");
//接收从服务器返回的数据
String s = null;
if ((s = dis.readUTF()) != null) {
System.out.println(s);
}
dos.close();
dis.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
}
通过这个简单的小Demo,我们就可以清晰的观察到Socket是如何在服务器端和客户端进行通信的。
J2SE是JavaWeb和J2EE的基础,异常处理、IO通道、线程、网络编程、GUI编程又是J2SE的基础,所以学好Socket很有必要。
席慕蓉说过一句名言:前世的五百次回眸才能换得今生的一次擦肩而过。所以对于以后的每次擦肩而过都应该认真对待,不要像我,和Socket都擦肩而过好多次了,今天才终于认识它。