15 网络编程
网络编程:
计算机网络
* 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,
在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系
统。
网络编程
* 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络编程三要素ip:
* 每个设备在网络中的唯一标识
* 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
* 本地回路地址:127.0.0.1 255.255.255.255是广播地址
* IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
* IPv6:8组,每组4个16进制数。
网络编程三要素端口:
每个程序在设备上的唯一标识
* 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个
程序。
* 端口号范围从0-65535
* 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用
。
* 常用端口
* mysql: 3306
* oracle: 1521
* web: 80
* tomcat: 8080
* QQ: 4000
* feiQ: 2425
网络编程三要素协议:
计算机网络中进行数据交换而建立的规则、标准或约定的集合。
UDP
* 面向无连接,数据不安全,速度快。不区分客户端与服务端。
TCP
* 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
* 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据
Socket套接字概述:
* 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
* 通信的两端都有Socket。
* 网络通信其实就是Socket间的通信。
* 数据在两个Socket间通过IO流传输。
* Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和
port。
UDP:
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.Scanner; public class Demo1_send { /*UDP 发送Send * 创建DatagramSocket, 随机端口号 * 创建DatagramPacket, 指定数据, 长度, 地址, 端口 * 使用DatagramSocket发送DatagramPacket * 关闭DatagramSocket*/ public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(); Scanner scanner = new Scanner(System.in); while(true) { String string = scanner.nextLine(); if ("quit".equals(string)) { break; } byte[] buf = string.getBytes(); int length = buf.length; InetAddress address = InetAddress.getByName("127.0.0.1"); int port = 8000; DatagramPacket packet = new DatagramPacket(buf, length, address, port); socket.send(packet); } socket.close(); } }
import java.net.DatagramPacket; import java.net.DatagramSocket; public class Demo2_rec { /*UDP 接收Receive * 创建DatagramSocket, 指定端口号 * 创建DatagramPacket, 指定数组, 长度 * 使用DatagramSocket接收DatagramPacket * 关闭DatagramSocket * 从DatagramPacket中获取数据*/ public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(8000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while(true) { socket.receive(packet); // 接受数据 byte[] arr = packet.getData(); // 获取数据 int len = packet.getLength(); // 获取有效的字节个数 String ip = packet.getAddress().getHostAddress(); //ip int port = packet.getPort(); //port System.out.println(ip+":"+port+":"+new String(arr,0,len)); } } }
UDP传输多线程:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Scanner; public class Demo3_ManyThread { public static void main(String[] args) { // UDP传输多线程 new Receive().start(); new Send().start(); } } class Receive extends Thread{ public void run() { try { DatagramSocket socket = new DatagramSocket(8000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while(true) { socket.receive(packet); // 接受数据 byte[] arr = packet.getData(); // 获取数据 int len = packet.getLength(); // 获取有效的字节个数 String ip = packet.getAddress().getHostAddress(); //ip int port = packet.getPort(); //port System.out.println(ip+":"+port+":"+new String(arr,0,len)); } } catch (IOException e) { e.printStackTrace(); } } } class Send extends Thread{ public void run() { try { DatagramSocket socket = new DatagramSocket(); Scanner scanner = new Scanner(System.in); while(true) { String string = scanner.nextLine(); if ("quit".equals(string)) { break; } byte[] buf = string.getBytes(); int length = buf.length; InetAddress address = InetAddress.getByName("127.0.0.1"); int port = 8000; DatagramPacket packet = new DatagramPacket(buf, length, address, port); socket.send(packet); } socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
TCP协议:
import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class Demo1_Client { /*客户端 * 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器 * 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流 * 输入流可以读取服务端输出流写出的数据 * 输出流可以写出数据到服务端的输入流*/ public static void main(String[] args) throws Exception { Socket socket = new Socket("127.0.0.1", 8000); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); byte[] b = new byte[1024]; int len = is.read(b); System.out.println(new String(b, 0, len)); os.write("自动回复".getBytes()); socket.close(); } }
import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class Demo1_Server { /*服务端 * 创建ServerSocket(需要指定端口号) * 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket * 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流 * 输入流可以读取客户端输出流写出的数据 * 输出流可以写出数据到客户端的输入流*/ public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(8000); Socket socket = server.accept(); InputStream io = socket.getInputStream(); OutputStream os = socket.getOutputStream(); os.write("我是服务器".getBytes()); byte[] b = new byte[1024]; int len = io.read(b); System.out.println(new String(b,0,len)); socket.close(); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; public class Demo2_Client { public static void main(String[] args) throws Exception, IOException { //客户端 Socket socket = new Socket("127.0.0.1", 8000); //将字节流包装成了字符流 BufferedReader br = new BufferedReader(new InputStreamReader (socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream());////PrintStream 中有写出换行的方法 System.out.println(br.readLine()); ps.println("ping:127.0.0.1"); System.out.println(br.readLine()); ps.println("haha"); socket.close(); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; public class Demo2_Server { public static void main(String[] args) throws Exception { //多线程服务端 ServerSocket server = new ServerSocket(8000); while(true) { Socket socket = server.accept(); new Thread() { public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream (socket.getOutputStream()); ps.println("你已经连通"); System.out.println(br.readLine()); ps.println("hihi"); System.out.println(br.readLine()); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
练习1:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class Test1_Client { //客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取 到是反转后的字符串 public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); Socket socket = new Socket("127.0.0.1", 8000); BufferedReader br = new BufferedReader(new InputStreamReader (socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println(scanner.nextLine()); System.out.println(br.readLine()); socket.close(); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; public class Test1_Server { // 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到 是反转后的字符串 public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(8000); while(true) { Socket socket = server.accept(); new Thread() { public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream (socket.getOutputStream()); String line = br.readLine(); line = new StringBuilder(line).reverse ().toString(); //反转后写回去 ps.println(line); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
练习2:
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class Test2_Client { // 客户端向服务器上传文件 public static void main(String[] args) throws Exception { File file = getFile(); Socket socket = new Socket("127.0.0.1", 8000); BufferedReader br = new BufferedReader(new InputStreamReader (socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println(file.getName()); String res = br.readLine(); if ("已存在".equals(res)) { System.out.println("文件已存在"); socket.close(); return; } //不存在, 定义FileInputStream读取文件, 写出到网络 FileInputStream fis = new FileInputStream(file); byte[] b = new byte[2048]; int len; while((len=fis.read(b))!=-1) { ps.write(b, 0, len); } fis.close(); socket.close(); } private static File getFile() { //录入文件路径 Scanner scanner = new Scanner(System.in); System.out.println("请输入文件路径:"); while(true) { String string = scanner.nextLine(); File file = new File(string); if (!file.exists()) { System.out.println("不存在"); }else if (file.isDirectory()) { System.out.println("文件夹,干嘛?"); }else { return file; } } } }
import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; public class Test2_Server { // 客户端向服务器上传文件 public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(8000); while(true) { final Socket socket = server.accept(); new Thread() { public void run() { try { InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream (socket.getOutputStream()); String fileName = br.readLine(); // 判断文件是否存在, 将结果发回客户端 File dir = new File("update"); dir.mkdir(); File file = new File(dir, fileName); if (file.exists()) { ps.println("已存在"); socket.close(); return; }else { ps.println("正在上传..."); } FileOutputStream fos = new FileOutputStream(file); byte[] b = new byte[2048]; int len; while((len=is.read(b))!=-1) { fos.write(b, 0, len); } fos.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
练习3:
import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Event; import java.awt.Font; import java.awt.Frame; import java.awt.Panel; import java.awt.TextArea; import java.awt.TextField; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.Date; import javax.imageio.IIOParam; public class Demo4_GUIChat extends Frame{ private TextField tf; private Button send; private Button log; private Button clear; private Button shake; private TextArea viewText; private TextArea sendText; private DatagramSocket socket; private BufferedWriter bufferedWriter; public Demo4_GUIChat() { centerPanel(); southPanel(); init(); event(); } private void event() { //关闭 this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { try { socket.close(); bufferedWriter.close(); } catch (IOException e1) { e1.printStackTrace(); } System.exit(0); } }); //发送 send.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { send(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); //记录 log.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { logFile(); } catch (IOException e1) { e1.printStackTrace(); } } }); //清屏 clear.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { viewText.setText(""); } }); //震动 shake.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { send(new byte[] {-1}, tf.getText()); } catch (IOException e1) { e1.printStackTrace(); } } }); //回车或ctrl+s发送 sendText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode()==KeyEvent.VK_ENTER || e.isControlDown() &&(e.getKeyCode()==KeyEvent.VK_S)) { try { send(); } catch (IOException e1) { e1.printStackTrace(); } } } }); } private void shake() { int x = this.getLocation().x; //获取横坐标位置 int y = this.getLocation().y; //获取纵坐标位置 for(int i = 0; i < 20; i++) { try { this.setLocation(x + 20, y + 20); Thread.sleep(20); this.setLocation(x + 20, y - 20); Thread.sleep(20); this.setLocation(x - 20, y + 20); Thread.sleep(20); this.setLocation(x - 20, y - 20); Thread.sleep(20); this.setLocation(x, y); } catch (InterruptedException e) { e.printStackTrace(); } } } private void logFile() throws IOException { bufferedWriter.flush(); //刷新缓冲区 FileInputStream fis = new FileInputStream("log.txt"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int len; byte[] b = new byte[2048]; while((len=fis.read(b))!=-1) { baos.write(b,0,len); } String str = baos.toString(); viewText.setText(str); fis.close(); baos.close(); } public void send(byte[] b, String ip) throws IOException { DatagramPacket packet = new DatagramPacket(b, b.length, InetAddress.getByName(ip), 8000); socket.send(packet); } private void send() throws IOException { String message = sendText.getText(); //发送区内容 String ip = tf.getText(); ip = ip.trim().length()==0 ? "255.255.255.255" : ip; send(message.getBytes(), ip); String time = getCurrentTime(); String str = time+" "+"@"+(ip.equals("255.255.255.255")?"所有人":ip)+":\r \n"+message+"\r\n\r\n"; //alt+shift+l抽取局部变量 viewText.append(str); bufferedWriter.write(str); // 将消息写到文件中 sendText.setText(""); } private String getCurrentTime() { // 获取当前时间 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("y年MM月dd日HH:mm:ss"); return sdf.format(date); } public void centerPanel() { Panel center = new Panel(); //创建中间 的Panel viewText = new TextArea(); sendText = new TextArea(5,1); center.setLayout(new BorderLayout()); //设置为边界布局管理器 center.add(sendText,BorderLayout.SOUTH); //发送的文本区域放在南边 center.add(viewText,BorderLayout.CENTER); //显示区域放在中间 viewText.setEditable(false); //设置不可以编辑 viewText.setBackground(Color.lightGray); //设置背景颜色 sendText.setFont(new Font("name1", Font.PLAIN, 15)); viewText.setFont(new Font("name2", Font.PLAIN, 15)); this.add(center,BorderLayout.CENTER); } public void southPanel() { Panel south = new Panel(); tf = new TextField(15); tf.setText("127.0.0.1"); send = new Button("发送"); log = new Button("记录"); clear = new Button("清屏"); shake = new Button("震动"); south.add(tf); south.add(send); south.add(log); south.add(clear); south.add(shake); this.add(south,BorderLayout.SOUTH); } public void init(){ this.setSize(400, 600); this.setLocation(500, 50); this.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png")); new Receive().start(); try { socket = new DatagramSocket(); bufferedWriter = new BufferedWriter(new FileWriter ("log.txt",true)); } catch (Exception e) { e.printStackTrace(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.setVisible(true); } private class Receive extends Thread{ //接收 public void run() { try { DatagramSocket socket = new DatagramSocket(8000); DatagramPacket packet = new DatagramPacket(new byte[2048], 2048); while(true) { socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); if (arr[0]==-1 && len==1) { shake(); //震动 continue; } String message = new String(arr, 0, len); String time = getCurrentTime(); String ip = packet.getAddress().getHostAddress(); String str = time+" "+ip+"@me"+":\r\n"+message+"\r \n\r\n"; viewText.append(str); bufferedWriter.write(str); sendText.setText(""); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { //GUI聊天 new Demo4_GUIChat(); } }

浙公网安备 33010602011771号