Java 网络编程学习总结
新手一枚,Java学习中,把自己学习网络编程的知识总结一下,梳理下知识,方便日后查阅,高手莫进。
本文的主要内容:
[1] 网络编程认识
[2] TCP/IP编程小例子
[3] UDP编程小例子
[4] 简单线程池实例
一、网络编程的主要认识
Java是一种基于网络设计的语言,用于开发网络软件特别便利。
它对于网络的操作都是基于IP层以上的,也就是对TCP/UDP进行操作,所以java的网络编程又称为Socket编程。
一种是TCP/IP 网络编程,
一种是UDP编程。
TCP是Tranfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送 或接收操作。
UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
另外,网络编程不同于WEB编程。
此处只把我自己学习时写的两个小例子贴出来。
关于Java网络编程更详细的介绍,感觉一些前辈总结的不错,贴出地址,各位如有需要,可以自己查阅。
http://www.cnblogs.com/springcsc/archive/2009/12/03/1616413.html
二、 TCP/IP编程
服务端代码:
1 import java.io.BufferedReader; 2 import java.io.DataInputStream; 3 import java.io.DataOutputStream; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 public class Server { 10 public static void main(String[] args) throws IOException { 11 ServerSocket server = new ServerSocket(8888);// 实例化一个ServerSocket对象那个,用于监视服务器的 12 // 8888 端口 13 Socket socket = server.accept();// 调用access()阻塞方法,等待客户端发送数据过来 14 // 设置输入缓冲流,把键盘输入的数据保存在流中 15 BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); 16 // 用两个数据流来读取和输出ServerSocket对象server的接收数据和发送数据 17 DataOutputStream write = new DataOutputStream(socket.getOutputStream()); 18 DataInputStream read = new DataInputStream(socket.getInputStream()); 19 // 阻塞方法,接收数据 20 String line = read.readUTF(); 21 22 while (line != "bye") { 23 // 输出接受的数据 24 System.out.println(socket.getInetAddress() + " : " + socket.getPort() + " say:" + line); 25 // 阻塞方法,接收用户键盘输入的数据,用于发送给客户端 26 line = input.readLine(); 27 System.out.println("server say:" + line); 28 // 服务器发送数据 29 write.writeUTF(line); 30 line = read.readUTF(); 31 } 32 // 关闭流和ServerSocket 33 read.close(); 34 write.close(); 35 input.close(); 36 socket.close(); 37 server.close(); 38 } 39 }
Client 端代码
1 import java.io.BufferedReader; 2 import java.io.DataInputStream; 3 import java.io.DataOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.PrintWriter; 8 import java.net.Socket; 9 import java.net.UnknownHostException; 10 11 public class Client { 12 public static void main(String[] args) throws IOException { 13 BufferedReader inputStream = null; 14 DataInputStream reader = null; 15 DataOutputStream writer = null; 16 Socket socket = null; 17 String line = null; 18 // 实例化Socket 用于指定所要发送数据的目标地址为127.0.0.1。端口为8888 19 socket = new Socket("127.0.0.1", 8888); 20 21 inputStream = new BufferedReader(new InputStreamReader(System.in)); 22 reader = new DataInputStream(socket.getInputStream()); 23 writer = new DataOutputStream(socket.getOutputStream()); 24 25 line = inputStream.readLine(); 26 27 while (line != "bye") { 28 System.out.println("client say: " + line); 29 writer.writeUTF(line); 30 line = reader.readUTF(); 31 System.out.println("server say: " + line); 32 line = inputStream.readLine(); 33 } 34 inputStream.close(); 35 reader.close(); 36 writer.close(); 37 socket.close(); 38 39 } 40 }
三、UDP编程
服务端代码:
1 import java.io.ByteArrayInputStream; 2 import java.io.DataInputStream; 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 7 public class UDPServer { 8 public static void main(String[] args) throws IOException { 9 // 定义缓冲区大小 10 byte[] buff = new byte[1024]; 11 // 实例化一个DatagramPacket对象,用于接受消息 12 DatagramPacket packet = new DatagramPacket(buff, buff.length); 13 DatagramSocket socket = new DatagramSocket(8888); 14 while (true) { 15 // 阻塞方法 16 socket.receive(packet); 17 ByteArrayInputStream bais = new ByteArrayInputStream(buff, 0, packet.getLength()); 18 DataInputStream stream = new DataInputStream(bais); 19 long l = stream.readLong(); 20 System.out.println(l); 21 } 22 } 23 }
Client端代码:
1 import java.io.ByteArrayOutputStream; 2 import java.io.DataOutputStream; 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.InetSocketAddress; 7 8 public class UDPClient { 9 public static void main(String[] args) throws IOException { 10 // 发送long类型数据 11 long n = 100000L; 12 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 13 DataOutputStream outputStream = new DataOutputStream(baos); 14 outputStream.writeLong(n); 15 byte[] buff = baos.toByteArray(); 16 DatagramPacket packet = new DatagramPacket(buff, buff.length, new InetSocketAddress("127.0.0.1", 8888)); 17 DatagramSocket socket = new DatagramSocket(9999); 18 socket.send(packet); 19 socket.close(); 20 } 21 }
四、简单的线程池代码:
1 import java.util.LinkedList; 2 3 public class TestThreadPool { 4 public static void main(String[] args) { 5 int numThreads = 3; 6 MyThreadPool pool = new MyThreadPool(numThreads); 7 int numTasks = 10; 8 for (int i = 0; i < numTasks; i++) { 9 pool.performTask(new MyTask(i)); 10 } 11 pool.join(); 12 } 13 14 } 15 16 // 线程池类,继承自ThreadGroup 17 class MyThreadPool extends ThreadGroup { 18 private boolean isAlive;// 表示线程池是否可以使用 19 private LinkedList taskQueue;// 工作队列 20 private int threadId;// 线程池内线程id 21 private static int threadPoolId;// 线程池id,可以实例化多个线程池 22 23 public MyThreadPool(int numThreads) 24 { 25 super("threadPoolID" + (threadPoolId++)); 26 super.setDaemon(true); 27 this.isAlive = true; 28 // 初始化工作队列 29 this.taskQueue = new LinkedList(); 30 for (int i = 0; i < numThreads; i++) { 31 // PooledThread是处理工作的线程类 32 new PooledThread().start(); 33 } 34 } 35 36 /** 添加新任务 */ 37 public synchronized void performTask(Task task) { 38 if (!this.isAlive) { 39 throw new IllegalStateException(); 40 } 41 if (task != null) { 42 this.taskQueue.add(task); 43 notify(); 44 } 45 } 46 47 /** 48 * 获取任务 49 * @throws InterruptedException 50 */ 51 protected synchronized Task getTask() throws InterruptedException { 52 while (this.taskQueue.size() == 0) { 53 if (!this.isAlive) 54 return null; 55 this.wait(); 56 } 57 return (Task) this.taskQueue.removeFirst(); 58 } 59 60 /** 关闭线程池,所有线程停止,不再执行 */ 61 public synchronized void close() { 62 if (this.isAlive) { 63 this.isAlive = false; 64 this.taskQueue.clear(); 65 this.interrupt(); 66 } 67 } 68 69 /** 关闭线程池,并等待线程池中所有任务运行完成,不能接受新任务 */ 70 public void join() { 71 synchronized (this) { 72 isAlive = false; 73 notifyAll(); 74 } 75 Thread[] threads = new Thread[this.activeCount()]; 76 int count = this.enumerate(threads); 77 for (int i = 0; i < count; i++) { 78 try { 79 threads[i].join(); 80 } catch (InterruptedException e) { 81 // TODO Auto-generated catch block 82 e.printStackTrace(); 83 } 84 } 85 } 86 87 // 内部类,用于执行任务的工作线程 88 class PooledThread extends Thread { 89 public PooledThread() 90 { 91 super(MyThreadPool.this, "PooledThread" + (threadId++)); 92 } 93 94 public void run() { 95 while (!Thread.interrupted()) { 96 // 获取任务 97 Task task = null; 98 try { 99 task = getTask(); 100 } catch (InterruptedException e) { 101 // TODO Auto-generated catch block 102 e.printStackTrace(); 103 } 104 if (task == null) 105 return; 106 try { 107 task.perform(); 108 } catch (Exception e) { 109 // TODO Auto-generated catch block 110 e.printStackTrace(); 111 } 112 113 } 114 } 115 } 116 117 } 118 119 // 定义任务的接口类 120 interface Task { 121 /** 122 * 执行任务 执行过程中可能出现异常 123 */ 124 public void perform() throws Exception; 125 } 126 127 // 实现上面接口的任务类 128 class MyTask implements Task { 129 private int TaskId = 0; 130 131 public MyTask(int id) 132 { 133 this.TaskId = id; 134 } 135 136 @Override 137 public void perform() throws Exception { 138 System.out.println("MyTask " + TaskId + " Start"); 139 Thread.sleep(1000); 140 System.out.println("MyTask " + TaskId + " end"); 141 } 142 143 }
最后,无论是TCP/IP 编程,还是UDP编程,都只是同步的,就用到的是阻塞方法,当服务器或者客户端没有发送来数据时,就一直处于等待状态。
最新的JDK已经推出了异步编程相关内容,我还有学习过,以后继续努力。