Java笔记 - Socket编程
两个Java应用程序可以通过一个双向的网络通讯连接实现数据交换,这个双向链路的一端称为一个Socket。java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向链路的client端和server端。建立连接时所需的寻址信息为远程计算机的IP地址和端口号(port number)。
注: 网络编程不等于网站编程,网站编程是基于网络编程基础之上。
一.、计算机网络
计算机网络把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而是众多的计算机可以方便的互相传递信息、共享硬件、软件、数据信息等资源。
计算机网络主要用于资源共享、信息传输与集中处理、均衡符合与分布处理、综合信息服务(综合业务数字网络/www、ISDN).
1、网络通讯模型
为了使两个节点之间能进行对话,必须在他们之间建立网络通信接口,使彼此之间能进行信息交换。接口包括 实现结点之间的信息传送的硬件设备 和 约定双方进行通讯时对速率、传输代码、代码结构、传输控制步骤、出错控制等标准的网络通讯协议。
(1)通讯协议分层
采用层次方式建立计算机网络模型,规定好每层的接口标准,同层之间可以通讯,上一层可以调用下一层,各层互不影响。
(2)数据传输过程
图1-1 数据封装
图 1-2 数据解封
2、IP与端口号
IP(Internet Protocol)协议是网际层的主要协议,支持网络互联的数据报通讯,它提供的主要功能有:无连接数据包传送、数据报路由选择和差错控制等。
IP地址为主机提供了独一无二的网络地址,分为IPv4(4字节)和IPv6(8字节)两种,由网络位和主机位组成。子网掩码使用1表示网络位、0表示主机位,用于判断两个IP是否在同一个网上。
端口号占2字节,分TCP端口和UDP端口两种,每一个都有65536个端口。注意端口号1024以下的被系统占用,如:80是HTTP端口、21是FTP端口、25是SNTP(简单邮件传输协议的端口)、100是POP3(邮件接收协议)的端口。服务器端口固定、客户端端口随机生成
3、TCP/UDP协议
(1)TCP(transmission controlprotocol)
TCP是一种面向连接的协议,可以提供可靠的、端到端的字节流通讯的协议。TCP连接是字节流而非报文流。如系统登录、文件传输等。
(2)UDP(user data protocol)
UDP向应用程序提供一种发生封装的原始IP数据报的方法、并且在发送时无需建立连接,传输速率快,是一种不可靠的连接。如视频和音频传输、实时通信、游戏等。
二、TCP通讯
1、点对点通讯
(1)Server端
1 import java.io.*; 2 import java.net.*; 3 public class Server 4 { 5 public static void main(String args[]) 6 { 7 try{ 8 ServerSocket server = new ServerSocket(5888);//监听5888端口 9 //同步式点对点Socket编程,读写顺序不能变 10 while(true) { 11 //接入客户端 12 Socket socket = server.accept(); 13 //获取输入输出流,TCP传输的是字节流 14 InputStream is = socket.getInputStream(); 15 OutputStream os = socket.getOutputStream(); 16 //套接输入输出流为 处理流+打印流 17 BufferedReader in = new BufferedReader(new InputStreamReader(is)); 18 PrintWriter out = new PrintWriter(os); 19 20 //服务器与客户端发送消息 21 BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); 22 String msg = "Server:你好,你已经可以和我通话了!"; //服务端发送的消息 23 while(!msg.equals("bye")) { 24 //发送服务端的消息 25 out.println(msg); 26 out.flush(); 27 //打印消息记录 28 System.out.println("Server:" + msg);//先打印服务端的消息 29 System.out.println("Client:" + in.readLine());//再打印客户端消息 30 //读取服务端输入的信息 31 msg = sin.readLine(); 32 } 33 34 //关闭连接 35 in.close(); 36 out.close(); 37 socket.close(); 38 server.close(); 39 } 40 }catch(IOException e){ 41 System.out.println("服务端运行出错"); 42 } 43 } 44 } 45
(2)Client端
1 import java.io.*; 2 import java.net.*; 3 public class Client 4 { 5 public static void main(String args[]) 6 { 7 try{ 8 //连接服务器IP的端口号(客户端发送数据的端口不定) 9 Socket socket = new Socket("127.0.0.1",5888); 10 11 //获取输入输出流,TCP传输的是字节流 12 InputStream is = socket.getInputStream(); 13 OutputStream os = socket.getOutputStream(); 14 //套接输入输出流为 缓冲流+打印流 15 BufferedReader in = new BufferedReader(new InputStreamReader(is)); 16 PrintWriter out = new PrintWriter(os); 17 18 //客户端与服务端发送消息 19 BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); 20 21 System.out.println("Server:" + in.readLine()); 22 String readline = sin.readLine(); 23 24 while (!readline.equals("bye")){ 25 out.println(readline); 26 out.flush(); 27 28 System.out.println("Client:" + readline); 29 System.out.println("Server:" + in.readLine()); 30 31 readline = sin.readLine(); 32 } 33 os.close(); 34 is.close(); 35 socket.close(); 36 }catch(Exception e){ 37 System.out.println("Error" + e); 38 } 39 } 40 }
2、异步式通讯
如Tomcat、Jboss
三、UDP通讯
1、简单的UDP通讯
(1)服务端
1 import java.net.*; 2 import java.io.*; 3 4 public class TestUDPServer 5 { 6 public static void main(String args[]) throws Exception 7 { 8 //设置缓冲区大小 9 byte buf[] = new byte[1024]; 10 //设置接收数据报的缓冲区 11 DatagramPacket dp = new DatagramPacket(buf, buf.length); 12 //设置服务端接受信息的端口 13 DatagramSocket ds = new DatagramSocket(5678); 14 while(true) 15 { 16 //接受数据报 17 ds.receive(dp); 18 //转换long类型数据 19 ByteArrayInputStream bais = new ByteArrayInputStream(buf); 20 DataInputStream dis = new DataInputStream(bais); 21 System.out.println(dis.readLong()); 22 //转换字符数组为字符串,dp.getLength获取数据串长度 23 //System.out.println(new String(buf,0,dp.getLength())); 24 } 25 } 26 }
(2)客户端
1 import java.net.*; 2 import java.io.*; 3 4 public class TestUDPClient 5 { 6 public static void main(String args[]) throws Exception 7 { //将一个long类型装换成字符数组 8 long n = 10000L; 9 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 10 DataOutputStream dos = new DataOutputStream(baos); 11 byte[] buf = baos.toByteArray(); 12 dos.writeLong(n); 13 //将字符串转换成字符数组 14 //byte[] buf = (new String("Hello")).getBytes(); 15 16 //封装数据报 17 DatagramPacket dp = new DatagramPacket(buf, buf.length, 18 new InetSocketAddress("127.0.0.1", 5678)); 19 //设置客户端发送端口 20 DatagramSocket ds = new DatagramSocket(9999); 21 //发送数据报 22 ds.send(dp); 23 //关闭流 24 ds.close(); 25 } 26 }