java Network编程所需要的包:java.net java.io java.lang
java.net中所需要的类或接口:Socket ServerSocket DatagramSocket DatagramPacket URL URLConnection
java.io中所需要的类或接口:InputStream/OutputStream BufferedInputStream/BufferedOutputStream DataInputStream/DataOutputStream BufferedReader/PrintWriter ObjectInputStream/ObjectOutputStream
java.lang中所需要的类或接口:Thread Runnable
首先了解一下TCP协议(传输控制协议)与UDP协议(用户数据报协议)的区别
1.TCP是面向连接的协议,UDP是无连接协议,TCP只有服务器与客户端建立连接时才能传输数据。
2.可靠性,TCP在建立连接以后才传送数据,提供提交保证,UDP只管将数据发送出去,数据包中包括完整的目的地址和源地址,由自己决定路由,所以不能保证 数 据传输成功。
3.顺序性,TCP协议传输数据,接收方收到的数据是与发送时的顺序保持一致的,UDP则不具有顺序性。
4.速度,UDP的传输速度要比TCP快。
5.数据边界,TCP不具有数据边界。
6.TCP为重量级的,UDP为轻量级的。
7.TCP比UDP的有更大的头部。 TCP数据包的报头通常大小为20字节,这是两倍以上的8个字节,UDP数据报分组的报头大小。 TCP报头中包含序列号,确认 号,数据偏移,保留,控制位,窗,紧急指针,选择,填充,校验和,源端口和目的端口。而UDP报头只包含长度,源端口,目的端口,校验和。
8.TCP做流量控制。 TCP要求三包建立socket连接,任何用户都可以将数据发送之前。 TCP处理可靠性和拥塞控制。另一方面,UDP不具有用于流控制的选项。
9.用途,使用TCP,如果你不能承受失去任何消息,而UDP是一种用于高速数据的传输,其中单个数据包的丢失是可以接受的,例如更好视频流或在线多玩家游 戏。
Client:
1.创建Socket,发起请求
2.从Socket中获取输入或输出流InputStream OutputStram
3.包装流
4.进行读写操作
当客户端进行写操作时,请求发送到服务器(服务器响应之前程序阻塞),然后进行读操作,读取服务器信息。
5.释放资源(流和Socket)
实例(使用Socket连接客户端与服务器端,并获取服务器的时间)
TcpClient.java
import java.io.BufferedReader;
import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;public class TcpClient {
public static void main(String[] args) { Socket client=null; PrintWriter pw=null; BufferedReader br=null; try { //构建Socket client=new Socket("localhost",8888); //获取输入输出流 OutputStream os=client.getOutputStream(); InputStream is=client.getInputStream(); //包装 pw=new PrintWriter(os); br=new BufferedReader(new InputStreamReader(is)); pw.println("I'm"+InetAddress.getLocalHost().getHostName()+"Please give me your time:"); pw.flush(); //程序会阻塞 String msg=br.readLine(); System.out.println(msg); } catch (Exception e) { e.printStackTrace(); }finally{ try { if(pw!=null)pw.close(); if(br!=null)br.close(); if(client!=null)client.close(); } catch (Exception e) { e.printStackTrace(); } } }}TcpServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;public class TcpServer {
public static void main(String[] args) { ServerSocket server=null; Socket client=null; PrintWriter pw=null; BufferedReader br=null; try { //构建ServerSocket server=new ServerSocket(8888); //使用accept方法从客户端获取Socket while(true){ client=server.accept(); //获取输入输出流 br=new BufferedReader(new InputStreamReader(client.getInputStream())); pw=new PrintWriter(new OutputStreamWriter(client.getOutputStream())); //读写操作 String msg=br.readLine(); System.out.println(msg); Date date=new Date(); pw.println("Now is:"+date); pw.flush(); //释放资源 if(pw!=null)pw.close(); if(br!=null)br.close(); if(client!=null)client.close(); } } catch (Exception e) { e.printStackTrace(); } }}将上边的服务端改为多线程处理
ServerThread.java
import java.io.BufferedReader;
import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.util.Date;public class ServerThread extends Thread{
private Socket client; public ServerThread(Socket client){ this.client=client; } public void run(){ try { BufferedReader br; br = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter pw; pw = new PrintWriter(new OutputStreamWriter(client.getOutputStream())); //读写操作 String msg=br.readLine(); System.out.println(msg); Date date=new Date(); pw.println("Now is:"+date); pw.flush(); sleep(100); //释放资源 if(pw!=null)pw.close(); if(br!=null)br.close(); if(client!=null)client.close();} catch(Exception e){ e.printStackTrace(); } }}在Server中使用死循环接受客户端请求,并启动ServerThread线程
TcpServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;public class TcpServer {
public static void main(String[] args) { ServerSocket server=null; Socket client=null; try { //构建ServerSocket server=new ServerSocket(8888); //使用accept方法从客户端获取Socket while(true){ client=server.accept(); new ServerThread(client).start(); } } catch (Exception e) { e.printStackTrace(); } }}URL Connections
URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。而URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。而URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的,schema必须被指定。
URL输入URI的一种 URI(范围更大):URL URN
//创建URL
URL url=new URL("http://www.baidu.com")
URLConnection conn=url.OpenConnection()
//连接服务器
conn.connect()
conn.getHeaderFieldKey(n)
conn.getHeaderField(n)
//得到一个输入流并且封装它
BufferedReader in=new BufferedReader(new InputStreamReader(conn.getInputStream()))
//从流中读取信息
line=in.readLine()