一.网络通讯,常见的结构是C/S模式。客户端在须要服务时向服务器请求链接,服务端被动接收链接,创建链接后,双方开始通讯。服务器进程通常做为守护进程,一直运行,不断监听网络端口,被动接收客户端的请求,当接收到客户的请求时,会启动一个服务进程来处理客户的请求,并继续监听网络端口。html
(上图转自:http://tutorials.jenkov.com/java-networking/index.html)java
二.网络上进程之间经过双向的通讯链接来实现信息的交换。这样链接的一端称为一个Socket。Socket由IP号和端口号肯定。在java中使用Socket来实现基于TCP/IP协议的网络程序,主要涉及到下面几步:服务器
客户端:网络
1.根据服务器的IP和端口号,创建Socketsocket
2.打开输入、输出流this
3.对Socket进行读写spa
4.关闭输入、输出流,关闭套接字.net
服务器端:线程
1.根据端口号创建ServerSocketcode
2.被动监听客户端请求
3.当监听到客户端请求时,接收请求,启动工做线程,处理请求。若再也不接收请求时,进入4;不然,继续监听,转2
4.关闭ServerSocket
下面以例子来讲明:
客户端代码:
package com.net.examples; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class Client { /** * @param args * @throws IOException * @throws UnknownHostException * @throws InterruptedException */ public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException { //这里假设有三个client,每一个client分别发送一次请求 int clientCount = 3; MyRunable run = new MyRunable(); while(clientCount > 0){ //每一个线程模拟一个client,三个线程名分别为1,2,3 new Thread(run,clientCount+"").start(); clientCount--; } } } //定义MyRunable,重写run方法实现client线程 class MyRunable implements Runnable{ public void run() { int messCount = 2; Socket socket = null; DataOutputStream o = null; DataInputStream in = null; try { //1.建立Socket,创建链接 socket = new Socket("127.0.0.1",8080); //2.打开输入输出流 o = new DataOutputStream(socket.getOutputStream()); in = new DataInputStream(socket.getInputStream()); System.out.println("Clients begin send messages"); //每一个client对Socket写两次 while(messCount > 0 ){ try { //3.对Socket进行写 o.writeUTF("" + messCount); o.flush(); } catch (IOException e) { e.printStackTrace(); } System.out.println("I am client:"+Thread.currentThread().getName() +",I send message:" + messCount); messCount--; } //对Socket进行读 System.out.println("I am client:" + Thread.currentThread().getName() + ",and server "+ in.readUTF() + "(me!)"); } catch (IOException e2) { e2.printStackTrace(); } finally{ try { //4.关闭输入输出流,关闭socket,释放资源 o.close(); in.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
服务端代码:
package com.net.examples; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; //Server public class Server { private static int clientCount = 3; //Server线程结束运行条件,这里是假设知道一共会收到三次客户端请求 private static boolean isStop(){ return clientCount == 0 ? true:false; } public static void main(String[] args) throws IOException, InterruptedException { //1.创建ServerSocket ServerSocket serverSocket = new ServerSocket(8080); //2.监听客户端请求 while(!isStop()){ //3.接收到客户端请求,并启动一个线程处理 Socket client = serverSocket.accept(); new MyThread(client,clientCount).start(); clientCount--; } //4.关闭ServerSocket serverSocket.close(); } } //客户端请求处理线程 class MyThread extends Thread{ private Socket clientSocket; private int id; private DataInputStream input; private DataOutputStream output ; public MyThread (){ } public MyThread(Socket soc,int i){ this.clientSocket = soc; this.id = i; } public void run(){ try { //得到输入输出流 input = new DataInputStream((clientSocket.getInputStream())); output = new DataOutputStream(clientSocket.getOutputStream()); int count = 2; //读取Socket while(count > 0){ System.out.println("I am server.I have received message:" + input.readUTF() + ",from" + id); count --; } //写Socket output.writeUTF("respose to client" + id); output.flush();; } catch (IOException e) { e.printStackTrace(); }finally { try { //释放资源,关闭链接 input.close(); output.close(); clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
运行结果以下:
client:
Server:
不过,后来我稍微地改了下Client.java文件中MyRunable.java,输出流o,在对Socket写完以后,就调用了o.close()方法,而不是在读完Socket后释放掉,从新跑程序后client跑的就有错出现了,Server程序没出错。具体如改动下红色的部分,而报错也以下图:
个人理解是,输出流不用了,因此就close()了,为何在读Socket时(58行的代码),会报socket closed这样的出错信息。难道调用o.close()时,会关闭socket??或者是其余缘由,实在不理解,刚刚看着java Socket这一块,好多不清楚。麻烦看到的童鞋帮解答下。。。