网络通讯的作用就是负责多个设备之间的数据交互,网络编程的方式主要分为两种,TCP协议和UDP协议,我们来看一下java对网络编程的支持
1.TCP:
TCP是一个有连接,可靠的协议。java主要支持API java.net.Socket 和 java.net.ServerSocket ,我们看一下例子
public class TestServerSocket implements Runnable{
/**
* 模拟 服务端
* <p>方法名称:</p>
* <p>方法说明:</p>
* @param args
* @throws IOException
* @throws InterruptedException
* @autho zx
* @time 2016年8月31日 下午4:38:01
*/
public static void main(String[] args) throws IOException, InterruptedException {
//1.绑定端口号
ServerSocket serverSocket = new ServerSocket(100);
Thread thread = new Thread(new TestServerSocket());
thread.start();
//2.起监听
Socket socket = serverSocket.accept();
//3.从client获取数据
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String readLine = bufferedReader.readLine();
System.out.println("server accept +_+ "+readLine);
//4.向client传输数据
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println(readLine+"from server");
printWriter.flush();
thread.join();
//5.关闭
serverSocket.close();
}
/**
* 模拟 客户端
* (non-Javadoc)
* @see java.lang.Runnable#run()
* @autho zx
* @time 2016年8月31日 下午4:38:15
*/
@Override
public void run() {
Socket socket = null;
try {
String IP = "10.0.114.26";
Integer poot = 100;
//1.绑定IP和端口号 IP为服务端所在机器的IP
socket = new Socket(IP, poot);
//2.向server传输数据
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println("hi~~");
printWriter.flush();
//3.从server接受数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String readLine = bufferedReader.readLine();
System.out.println(readLine);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
main线程模拟的是服务端,另外写了一个线程t 模拟客户端,在服务端,先创建一个ServerSocket并绑定端口,然后开始起监听accept 是一个阻塞方法,主要当它和客户端建立连接返回一个Socket对象的时候,程序才会往下执行,如果建立了连接,可以拿到 输入流和输出流,这里拿到的都是字节流,之后我们就可以进行I/O操作,最后不需要关闭流直接关闭socket对象就行。在客户端,我们直接绑定IP和端口拿到Socket,之后拿到流进行I/O操作,我们看一下结果
server accept +_+ hi~~
hi~~from server
当然这种只是一个例子,这个例子在启动程序后,只能让一个客户端访问,访问之后服务端的程序就会关闭,因此,我们会设置一个while(true)死循环,并且将I/O这部分操作专门写到一个线程中去。
2.UDP编程
UDP是一个无连接,不可靠的协议,它的核心API java.net.DatagramSocket 和 java.net.DatagramPacket ,这两个类理解的概念跟TCP的不一样,我在网上看过一篇文章,比喻的很好,可以将 DatagramSocket 作为传真机 将DatagramPacket 作为传真机需要的纸。
public class TestUDP implements Runnable{
/**
* 模拟 服务端
* <p>方法名称:</p>
* <p>方法说明:</p>
* @param args
* @throws IOException
* @autho zx
* @time 2016年8月31日 下午5:02:45
*/
public static void main(String[] args) throws IOException {
//1.绑定端口创建并传真机
DatagramSocket socket = new DatagramSocket(9999);
Thread t = new Thread(new TestUDP());
t.start();
//2.从client 接受数据
//2.1 创建传真机需要的白纸
byte[] bt = new byte[100];
DatagramPacket packet = new DatagramPacket(bt, bt.length);
//2.2 在白纸上渲染从客户端另一个传真机 传输的数据
socket.receive(packet);
//2.3 打印数据信息
SocketAddress socketAddress = packet.getSocketAddress();
System.out.println("client address:"+JSON.toJSONString(socketAddress));
int length = packet.getLength();
System.out.println("数据长度为 :"+length);
System.out.println(new String(bt));
//3.向client 传输数据
//3.1 创建需要发送的数据 传真纸
byte[] bytes = "hi~~ +_+ from server".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, socketAddress);
//3.2 将纸发送给客户端
socket.send(datagramPacket);
//4.关闭
socket.close();
}
/**
* 模拟 客户端
* (non-Javadoc)
* @see java.lang.Runnable#run()
* @autho zx
* @time 2016年8月31日 下午3:08:23
*/
@Override
public void run() {
try {
//1.创建传真机,IP 随机分配
DatagramSocket socket = new DatagramSocket();
//2.发送数据
//2.1 创建需要发送的数据
String data = "hello +_+ from client";
byte[] bytes = data.getBytes();
InetSocketAddress inetSocketAddress = new InetSocketAddress("10.0.114.26",9999);
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, inetSocketAddress);
//2.2 发送
socket.send(packet);
//3.接受数据
//3.1 创建白纸准备接受数据
byte[] bt = new byte[100];
DatagramPacket datagramPacket = new DatagramPacket(bt, bt.length, inetSocketAddress);
//3.2 接受数据
socket.receive(datagramPacket);
String str = new String(bt);
System.out.println(str);
//4.关闭
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注释已经很清楚了,不管在客户端还是服务端,首先都需要先创建一个传真机 DatagramSocket,当需要接受数据的时候,先创建一个白纸,接受之后
byte[] bt = new byte[100];
DatagramPacket packet = new DatagramPacket(bt, bt.length);
之后调用
socket.receive(packet);
方法进行接受数据。