一、网络基础(TCP/IP详解)
1、IP协议(Internet Protocol):网络层,支持网间数据报通信。无连接数据报传送,数据报路由选择和差错控制。
IPv4 32位(4字节),IPv6 128位(16字节)。P
ping ICMP协议
2、TCP协议、UDP协议
(1)TCP(transmission control protocol 打电话):专门设计用于在不可靠的因特网上提供可靠的、端到端的字节流通信的协议。它是一种面向连接的协议。有三次握手。慢
(2)UDP(user data protocol 寄信):提供了一种发送封装的原始IP数据报的方法、并且发送时无需建立连接,是一种不可靠的连接。快
二、Socket
两个Java应用程序可以通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket。
Socket通常用来实现client-server连接。
java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接(TCP连接)的client和server端。
建立连接时所需的寻址信息为远程计算机的IP地址和端口号(Port number)。端口号2字节,可以区分不同的应用程序。端口号又分TCP端口和UDP端口,每个都是65536个端口。
例如:
收邮件 POP3 110
STMP 25
FTP 21
HTTP 80
1、TCP Socket通信模型
这只是练习,实际上的网络编程都是异步式的。System.in,accept(),readUTF()都是阻塞式的(非重点)
例1
import java.net.*; import java.io.*; public class TCPServer{ public static void main(String args[]) throws Exception{ ServerSocket ss = new ServerSocket(6666);//端口号6666 while(true){ Socket s = ss.accept(); System.out.println("a client connect!"); DataInputStream dis = new DataInputStream(s.getInputStream()); System.out.println(dis.readUTF()); dis.close(); s.close(); } } }
import java.net.*; import java.io.*; public class TCPClient{ public static void main(String args[]) throws Exception{ Socket s = new Socket("127.0.0.1",6666); OutputStream os = s.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF("hello server!"); dos.flush(); dos.close(); s.close(); } }
例2
import java.io.*; import java.net.*; public class TestServer{ public static void main(String[] args){ try{ ServerSocket s = new ServerSocket(8888);//服务器端口号8888 while(true){ Socket s1 = s.accept(); OutputStream os = s1.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF("Hello,"+s1.getInetAddress()+"port#"+s1.getPort()+" byebye!");//客户端的IP地址和端口号 dos.close(); s1.close(); } }catch(IOException e){ e.printStackTrace(); } } }
import java.net.*; import java.io.*; public class TestClient{ public static void main(String[] args){ try{ Socket s1 = new Socket("127.0.0.1",8888);//服务器地址和端口号 InputStream is = s1.getInputStream(); DataInputStream dis = new DataInputStream(is); System.out.println(dis.readUTF()); dis.close(); s1.close(); }catch(ConnectException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } } }
例3
import java.io.*; import java.net.*; public class TestServer{ public static void main(String[] args){ InputStream in = null; OutputStream out = null; try{ ServerSocket ss = new ServerSocket(5888);//设置端口号 Socket s1 = ss.accept(); in = s1.getInputStream(); out = s1.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); DataInputStream dis = new DataInputStream(in); String s = null; if((s=dis.readUTF())!=null){ System.out.println(s); System.out.println("from: "+s1.getInetAddress()); System.out.println("Port: "+s1.getPort()); } dos.writeUTF("hi,hello"); dis.close(); dos.close(); s1.close(); }catch(IOException e){ e.printStackTrace(); } } }
import java.net.*; import java.io.*; public class TestClient{ public static void main(String[] args){ InputStream in = null; OutputStream out = null; try{ Socket s1 = new Socket("localhost",5888);//服务器地址和端口号 in = s1.getInputStream(); out = s1.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(); s1.close(); }catch(UnknownHostException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } } }
练习4:(by myself)
import java.io.*; import java.net.*; public class TestServer{ public static void main(String[] args){ InputStream in = null; OutputStream out = null; String si = null; String so = ""; try{ ServerSocket ss = new ServerSocket(5888);//设置端口号 while(true){ Socket s1 = ss.accept(); in = s1.getInputStream();//接收数据 out = s1.getOutputStream();//发送数据 DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); //从键盘读入 InputStreamReader isr2 = new InputStreamReader(System.in); BufferedReader br2 = new BufferedReader(isr2); while(!so.equals("exit")){ if((so=br2.readLine())!=null&&!so.equals("exit")){ System.out.println("Server:"+so); dos.writeUTF(so); } if((si=dis.readUTF())!=null){ System.out.println("Client:"+si); } } dis.close(); br2.close(); dos.close(); s1.close(); } }catch(IOException e){ e.printStackTrace(); } } }
import java.net.*; import java.io.*; public class TestClient{ public static void main(String[] args){ InputStream in = null; OutputStream out = null; String si = null; String so= ""; try{ Socket s1 = new Socket("127.0.0.1",5888);//服务器地址和端口号 in = s1.getInputStream();//接收 out = s1.getOutputStream();//发送 DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); //从键盘读入 InputStreamReader isr2 = new InputStreamReader(System.in); BufferedReader br2 = new BufferedReader(isr2); while(!so.equals("exit")){ if((si=dis.readUTF())!=null){ System.out.println("Server:"+si); } if((so=br2.readLine())!=null&&!so.equals("exit")){ System.out.println("Client:"+so); dos.writeUTF(so); } } dis.close(); br2.close(); dos.close(); s1.close(); }catch(UnknownHostException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } } }
2、UDP Socket通信模型
没有server,client的概念,不区分两者的socket。receive()方法也是阻塞式的。
例1
import java.net.*; public class TestUDPServer{ public static void main(String args[]) throws Exception{ byte buf[] = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); DatagramSocket ds = new DatagramSocket(5678); while(true){ ds.receive(dp); System.out.println(new String(buf, 0, dp.getLength())); } } }
import java.net.*; public class TestUDPClient{ public static void main(String args[]) throws Exception{ byte[] buf = (new String("Hello")).getBytes(); DatagramPacket dp = new DatagramPacket(buf, buf.length, new InetSocketAddress("127.0.0.1", 5678)); DatagramSocket ds = new DatagramSocket(9999); ds.send(dp); ds.close(); } }
例2
import java.net.*; import java.io.*; public class TestUDPServer{ public static void main(String args[]) throws Exception{ byte buf[] = new byte[1024]; ByteArrayInputStream bais = new ByteArrayInputStream(buf);//从字节数组读数据 DataInputStream dis = new DataInputStream(bais); DatagramPacket dp = new DatagramPacket(buf, buf.length); DatagramSocket ds = new DatagramSocket(5678); while(true){ ds.receive(dp); long l = dis.readLong(); System.out.println(l); } } }
import java.net.*; import java.io.*; public class TestUDPClient{ public static void main(String args[]) throws Exception{ long n = 10000L; ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeLong(n); byte[] buf = baos.toByteArray(); System.out.println(buf.length); DatagramPacket dp = new DatagramPacket(buf,buf.length,new InetSocketAddress("127.0.0.1",5678)); DatagramSocket ds = new DatagramSocket(9999); ds.send(dp); ds.close(); } }