目录

补充的一些快捷键

网络编程概述

网络编程三要素之IP概述

网络编程三要素之端口号概述

网络编程三要素之协议概述

Socket通信原理图解

UDP传输

UDP传输优化

UDP传输多线程

UDP聊天图形化界面

UDP聊天发送功能

UDP聊天记录功能

UDP聊天清屏功能

UDP聊天震动功能

UDP聊天快捷键和代码优化

UDP聊天生成jar文件

TCP协议

TCP协议代码优化

服务端是多线程的

网络编程练习一

网络编程练习二


补充的一些快捷键

Alt + Shift + Z 可以给选中的区域快速加try catch。网上给的解释是 重构的后悔药(Undo)

Alt + Shift + L 抽取局部变量

选中文件按 Alt + Shift + R 即可改名

选中局部变量按 Ctrl + 1 选择 Convert local variable tofield 可以将局部变量生成成员变量。


网络编程概述

计算机网络

是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

网络编程

就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。


网络编程三要素之IP概述

Windows10 控制面板 - 网络和共享中心 - 更改适配器设置 - 右键WLAN属性 - 选中Internet 协议版本 4 (TCP/IPv4)点属性 - 这个位置放的就是IP地址,可以在这里设置

查看IPv6地址:控制面板 - 网络和共享中心 - 更改适配器设置 - 右键WLAN属性 - 选中Internet 协议版本 6 (TCP/IPv6)点属性 - 这里可以设置IPv6地址

每个设备在网络中的唯一标识。

每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。 

命令:

ipconfig:查看本机IP 192.168.12.42

ping:测试连接 192.168.40.62

本地回路地址:127.0.0.1 (做网络编程练习,没有网(外网、局域网)的情况下,自己在家做,就可以用这个IP地址,自己给自己发一些数据) 255.255.255.255是广播地址 (应用:聊天室)

IPv4:4个字节组成,4个0 - 255。大概42亿(256的四次方),30亿都在北美,亚洲4亿。2011年初已经用尽。

IPv6:8组,每组4个16进制数。大概排列方式:八组太长,中间全是零的可以省略,然后两个冒号就连接在一起了。但如果有两组零,不能前后一起省略,因为这样做会无法得知前后到底有几个零。

1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f

1a2b::aaaa:0000:0000:0000:aabb:1f2f

1a2b:0000:aaaa::aabb:1f2f

1a2b:0000:aaaa::0000:aabb:1f2f

1a2b:0000:aaaa:0000::aabb:1f2f


网络编程三要素之端口号概述

每个程序在设备上的唯一标识。

每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上(IP地址),还要明确发到哪个程序(端口)。

端口号范围从0 - 65535。

编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。

常用端口

mysql:3306

oracle:1521

web:80

tomcat:8080

QQ:4000

feiQ:2425


网络编程三要素之协议概述

为计算机网络中进行数据交换而建立的规则、标准或约定的集合。

UDP

面向无连接,数据不安全,速度快。不区分客户端与服务端。类似于发短信的过程,不用担心对方在还是不在,有可能数据发丢了。

TCP

面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。

三次握手

客户端先向服务端发起请求,服务端响应请求,传输数据。(你瞅啥;瞅你咋地;来,咱俩唠唠)


Socket通信原理图解

Socket套接字概述:socket插座的意思

网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

通信的两端都需要有Socket。

网络通信其实就是Socket间的通信。

数据在两个Socket间通过IO流传输。

Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port端口号。可以将通信的两端理解为港口,Socket理解为码头,IO流理解为船,船在两个码头将来回传递数据。


UDP传输

发送Send

创建DatagramSocket, 随机端口号

创建DatagramPacket, 指定数据, 长度, 地址, 端口。相当于一个集装箱,将要发的货都装在箱子里,再发出去就行了

使用DatagramSocket发送DatagramPacket

关闭DatagramSocket

演示:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/***发送端*/
public class Demo1_Send {public static void main(String[] args) throws Exception {  //UnknownHostException不知道主机异常String str = "what are you 弄啥呢?";//创建Socket相当于创建码头DatagramSocket socket = new DatagramSocket();     //可以不指定端口号,因为他可以是随机端口号//创建Packet相当于集装箱DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);//发货,将数据发出去socket.send(packet);//关闭码头,因为其底层是IO流socket.close();}
}

接收Receive

创建DatagramSocket, 指定端口号

创建DatagramPacket, 指定数组, 长度

使用DatagramSocket接收DatagramPacket

关闭DatagramSocket

从DatagramPacket中获取数据

演示:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*** 接收端*/
public class Demo1_Receive {public static void main(String[] args) throws Exception {//创建Socket相当于创建码头DatagramSocket socket = new DatagramSocket(6666);//创建Packet相当于创建集装箱DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//接货,接收数据socket.receive(packet);//获取数据,无论数据是否有效byte[] arr = packet.getData();//获取有效的字节个数int len = packet.getLength();System.out.println(new String(arr, 0, len));socket.close();}
}

运行程序时,先开接收端,再开发送端,不然可能接收不到。


UDP传输优化

接收方获取ip和端口号

String ip = packet.getAddress().getHostAddress();

int port = packet.getPort();

接收端演示:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*** 接收端*/
public class Demo2_Receive {public static void main(String[] args) throws Exception {//创建Socket相当于创建码头DatagramSocket socket = new DatagramSocket(6666);//创建Packet相当于创建集装箱DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);while(true) {//不断地接货,接收数据socket.receive(packet);//不断地获取数据,无论数据是否有效byte[] arr = packet.getData();//不断地获取有效的字节个数int len = packet.getLength();//不断地获取ip地址String ip = packet.getAddress().getHostAddress();//不断地获取端口号int port = packet.getPort();System.out.println(ip + ":" + port + ":" + new String(arr, 0, len));}}
}

发送端演示:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/***发送端*/
public class Demo2_Send {public static void main(String[] args) throws Exception {  //UnknownHostException不知道主机异常//创建键盘录入对象Scanner sc = new Scanner(System.in);//创建Socket相当于创建码头DatagramSocket socket = new DatagramSocket();while(true) {//不断地获取键盘录入的字符串String line = sc.nextLine();//不断地对字符串做判断,直到输入字符串quitif("quit".equals(line)) {break;}//不断地创建Packet相当于集装箱DatagramPacket packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);//不断地发货,将数据发出去socket.send(packet);}//关闭码头,因为其底层是IO流socket.close();}
}

UDP传输多线程

利用多线程实现发送和接收在一个窗口完成。

演示:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;public class Demo3_MoreThread {public static void main(String[] args) throws InterruptedException {new Receive().start();Thread.sleep(500);        //让线程睡一会,防止Send线程先开启,保证Receive线程完全开启new Send().start();}
}class Receive extends Thread {public void run() {try {//创建Socket相当于创建码头DatagramSocket socket = new DatagramSocket(6666);//创建Packet相当于创建集装箱DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);while(true) {//不断地接货,接收数据socket.receive(packet);//不断地获取数据,无论数据是否有效byte[] arr = packet.getData();//不断地获取有效的字节个数int len = packet.getLength();//不断地获取ip地址String ip = packet.getAddress().getHostAddress();//不断地获取端口号int port = packet.getPort();System.out.println(ip + ":" + port + ":" + new String(arr, 0, len));}} catch (Exception e) {e.printStackTrace();}}
}class Send extends Thread {public void run() {try {//创建键盘录入对象Scanner sc = new Scanner(System.in);//创建Socket相当于创建码头DatagramSocket socket = new DatagramSocket();while(true) {//不断地获取键盘录入的字符串String line = sc.nextLine();//不断地对字符串做判断,直到输入字符串quitif("quit".equals(line)) {break;}//不断地创建Packet相当于集装箱DatagramPacket packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);//不断地发货,将数据发出去socket.send(packet);}//关闭码头,因为其底层是IO流socket.close();} catch (Exception e) {e.printStackTrace();}}
}

UDP聊天图形化界面

组件:

一个Frame。

两个Panel。

南部的Panel:一个TextField 四个Button。

中间的Panel:两个TextArea。

Font类的字段:

public static final int PLAIN 普通样式常量。

Font类的构造方法:

public Font(String name, int style, int size) 根据指定名称、样式和磅值大小,创建一个新 Font。 名称即字体名称,样式即字形(常规、斜体、粗体、粗体 斜体),磅值大小及大小。

演示:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/*** GUI聊天*/
public class Demo4_GUIChat extends Frame{public Demo4_GUIChat() {   //一创建子类对象,构造方法中的代码自动运行init();        //将代码抽取成一个方法,防止构造方法中的代码过于臃肿southPanel();centerPanel();event();}public void event() {this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});}public void centerPanel() {Panel center = new Panel();                    //创建中间的PanelTextArea viewText = new TextArea();            //显示的文本区域TextArea sendText = new TextArea(5, 1);       //发送的文本区域 参数设置行和列,即高和宽//Panel默认流式布局,而我们需要将两个文本区域一个放在Panel的南边,一个放在Panel的中间,应该用边界布局center.setLayout(new BorderLayout());      //设置为边界布局管理器center.add(sendText, BorderLayout.SOUTH);   //发送的文本区域放在南边center.add(viewText, BorderLayout.CENTER); //显示的文本区域放在中间viewText.setEditable(false);               //设置显示的文本区域不可以编辑viewText.setBackground(Color.WHITE);        //设置背景颜色 Color类中同一颜色有大写字段和小写字段两种,其实是一个东西。底层代码中,小写的静态常量被RGB三原色作为参数的Color对象赋值,大写的静态常量直接被小写的静态常量赋值。sendText.setFont(new Font("xxx", Font.PLAIN, 15));viewText.setFont(new Font("xxx", Font.PLAIN, 15));this.add(center, BorderLayout.CENTER);     //将Panel放在Frame的中间}public void southPanel() {Panel south = new Panel();                    //创建南边的PanelTextField tf = new TextField(15);          //创建文本字段存储ip地址 参数设置列,即宽Button send = new Button("发 送");               //创建发送按钮Button log = new Button("记 录");              //创建记录按钮Button clear = new Button("清 屏");            //创建清屏按钮Button shake = new Button("震 动");            //创建震动按钮south.add(tf);south.add(send);south.add(log);south.add(clear);south.add(shake);this.add(south, BorderLayout.SOUTH);         //将Panel放在Frame的南边}public void init() {this.setLocation(500, 50);this.setSize(400, 600);this.setVisible(true);}public static void main(String[] args) {new Demo4_GUIChat(); //创建一个Frame的子类对象,即创建一个窗体出来}
}

UDP聊天发送功能

演示:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*** GUI聊天*/
public class Demo4_GUIChat2 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;public Demo4_GUIChat2() { //一创建子类对象,构造方法中的代码自动运行init();        //将代码抽取成一个方法,防止构造方法中的代码过于臃肿southPanel();centerPanel();event();}public void event() {this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {socket.close();                        //在退出java虚拟机之前关流System.exit(0);}});send.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send();} catch (IOException e1) {e1.printStackTrace();}}});}private void send() throws IOException {       //send属于在主线程里跑 main() - 构造方法 - event() - send()String message = sendText.getText();        //获取发送区域的内容String ip = tf.getText();                   //获取ip地址DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, InetAddress.getByName(ip), 9999);socket.send(packet);                        //发送数据String time = getCurrentTime();              //获取当前时间viewText.append(time + " 我对:" + ip + " 说\r\n" + message + "\r\n\r\n");   //将信息添加到显示区域中sendText.setText("");                        //清除发送区域的内容}private String getCurrentTime() {Date d = new Date();                      //创建当前日期对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");return sdf.format(d);                      //将时间格式化}public void centerPanel() {Panel center = new Panel();                    //创建中间的PanelviewText = new TextArea();sendText = new TextArea(5, 1);//Panel默认流式布局,而我们需要将两个文本区域一个放在Panel的南边,一个放在Panel的中间,应该用边界布局center.setLayout(new BorderLayout());     //设置为边界布局管理器center.add(sendText, BorderLayout.SOUTH);   //发送的文本区域放在南边center.add(viewText, BorderLayout.CENTER); //显示的文本区域放在中间viewText.setEditable(false);               //设置显示的文本区域不可以编辑viewText.setBackground(Color.WHITE);        //设置背景颜色 Color类中同一颜色有大写字段和小写字段两种,其实是一个东西。底层代码中,小写的静态常量被RGB三原色作为参数的Color对象赋值,大写的静态常量直接被小写的静态常量赋值。sendText.setFont(new Font("xxx", Font.PLAIN, 15));viewText.setFont(new Font("xxx", Font.PLAIN, 15));this.add(center, BorderLayout.CENTER);     //将Panel放在Frame的中间}public void southPanel() {Panel south = new Panel();                    //创建南边的Paneltf = 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);      //将Panel放在Frame的南边}public void init() {this.setLocation(500, 50);this.setSize(400, 600);try {socket = new DatagramSocket();            //一初始化就创建码头} catch (SocketException e) {e.printStackTrace();}new Receive().start();                     //一初始化就开启接收,避免两条线程争抢执行权this.setVisible(true);}//内部定义一个内部类做接收端,方便调用外部类的方法(无论公有的还是私有的)private class Receive extends Thread {          //接收和发送需要同时执行,所以定义成多线程的public void run() {try {socket = new DatagramSocket(9999);DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);while(true) {socket.receive(packet);            //接收信息byte[] arr = packet.getData();       //获取字节数据int len = packet.getLength();      //获取有效的字节数据长度String message = new String(arr, 0, len);String time = getCurrentTime();     //获取当前时间String ip = packet.getAddress().getHostAddress();  //获取ip地址viewText.append(time + " " + ip + " 对我说:\r\n" + message + "\r\n\r\n");}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {new Demo4_GUIChat2();    //创建一个Frame的子类对象,即创建一个窗体出来}
}

UDP聊天记录功能

演示:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*** GUI聊天*/
public class Demo4_GUIChat3 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 bw;public Demo4_GUIChat3() {   //一创建子类对象,构造方法中的代码自动运行init();        //将代码抽取成一个方法,防止构造方法中的代码过于臃肿southPanel();centerPanel();event();}public void event() {this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {try {socket.close();                       //在退出java虚拟机之前关流bw.close();} catch (IOException e1) {e1.printStackTrace();}System.exit(0);}});send.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send();} catch (IOException e1) {e1.printStackTrace();}}});log.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {logFile();} catch (IOException e1) {e1.printStackTrace();}}});}private void logFile() throws IOException {bw.flush();                                   //刷新缓冲区FileInputStream fis = new FileInputStream("config.txt");ByteArrayOutputStream baos = new ByteArrayOutputStream();    //在内存中创建缓冲区int len;byte[] arr = new byte[8192];while((len = fis.read(arr)) != -1) {baos.write(arr, 0, len);}String str = baos.toString();               //将内存中的内容转换成了字符串viewText.setText(str);fis.close();}private void send() throws IOException {     //send属于在主线程里跑 main() - 构造方法 - event() - send()String message = sendText.getText();        //获取发送区域的内容String ip = tf.getText();                   //获取ip地址DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, InetAddress.getByName(ip), 9999);socket.send(packet);                        //发送数据String time = getCurrentTime();              //获取当前时间String str = time + " 我对:" + ip + " 说\r\n" + message + "\r\n\r\n";  //Alt + Shift + L 抽取局部变量viewText.append(str);                         //将信息添加到显示区域中bw.write(str);sendText.setText("");                      //清除发送区域的内容}private String getCurrentTime() {Date d = new Date();                      //创建当前日期对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");return sdf.format(d);                      //将时间格式化}public void centerPanel() {Panel center = new Panel();                    //创建中间的PanelviewText = new TextArea();sendText = new TextArea(5, 1);//Panel默认流式布局,而我们需要将两个文本区域一个放在Panel的南边,一个放在Panel的中间,应该用边界布局center.setLayout(new BorderLayout());     //设置为边界布局管理器center.add(sendText, BorderLayout.SOUTH);   //发送的文本区域放在南边center.add(viewText, BorderLayout.CENTER); //显示的文本区域放在中间viewText.setEditable(false);               //设置显示的文本区域不可以编辑viewText.setBackground(Color.WHITE);        //设置背景颜色 Color类中同一颜色有大写字段和小写字段两种,其实是一个东西。底层代码中,小写的静态常量被RGB三原色作为参数的Color对象赋值,大写的静态常量直接被小写的静态常量赋值。sendText.setFont(new Font("xxx", Font.PLAIN, 15));viewText.setFont(new Font("xxx", Font.PLAIN, 15));this.add(center, BorderLayout.CENTER);     //将Panel放在Frame的中间}public void southPanel() {Panel south = new Panel();                    //创建南边的Paneltf = 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);      //将Panel放在Frame的南边}public void init() {this.setLocation(500, 50);this.setSize(400, 600);try {socket = new DatagramSocket();            //一初始化就创建码头bw = new BufferedWriter(new FileWriter("config.txt", true));} catch (Exception e) {e.printStackTrace();}new Receive().start();                        //一初始化就开启接收,避免两条线程争抢执行权this.setVisible(true);}//内部定义一个内部类做接收端,方便调用外部类的方法(无论公有的还是私有的)private class Receive extends Thread {          //接收和发送需要同时执行,所以定义成多线程的public void run() {try {socket = new DatagramSocket(9999);DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);while(true) {socket.receive(packet);            //接收信息byte[] arr = packet.getData();       //获取字节数据int len = packet.getLength();      //获取有效的字节数据长度String message = new String(arr, 0, len);String time = getCurrentTime();     //获取当前时间String ip = packet.getAddress().getHostAddress();  //获取ip地址String str = time + " " + ip + " 对我说:\r\n" + message + "\r\n\r\n";viewText.append(str);bw.write(str);}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {new Demo4_GUIChat3();    //创建一个Frame的子类对象,即创建一个窗体出来}
}

UDP聊天清屏功能

演示:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*** GUI聊天*/
public class Demo4_GUIChat4 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 bw;public Demo4_GUIChat4() {   //一创建子类对象,构造方法中的代码自动运行init();        //将代码抽取成一个方法,防止构造方法中的代码过于臃肿southPanel();centerPanel();event();}public void event() {this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {try {socket.close();                       //在退出java虚拟机之前关流bw.close();} catch (IOException e1) {e1.printStackTrace();}System.exit(0);}});send.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send();} catch (IOException e1) {e1.printStackTrace();}}});log.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {logFile();} catch (IOException e1) {e1.printStackTrace();}}});clear.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {viewText.setText("");}});}private void logFile() throws IOException {bw.flush();                                  //刷新缓冲区FileInputStream fis = new FileInputStream("config.txt");ByteArrayOutputStream baos = new ByteArrayOutputStream();    //在内存中创建缓冲区int len;byte[] arr = new byte[8192];while((len = fis.read(arr)) != -1) {baos.write(arr, 0, len);}String str = baos.toString();               //将内存中的内容转换成了字符串viewText.setText(str);fis.close();}private void send() throws IOException {     //send属于在主线程里跑 main() - 构造方法 - event() - send()String message = sendText.getText();        //获取发送区域的内容String ip = tf.getText();                   //获取ip地址DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, InetAddress.getByName(ip), 9999);socket.send(packet);                        //发送数据String time = getCurrentTime();              //获取当前时间String str = time + " 我对:" + ip + " 说\r\n" + message + "\r\n\r\n";  //Alt + Shift + L 抽取局部变量viewText.append(str);                         //将信息添加到显示区域中bw.write(str);sendText.setText("");                      //清除发送区域的内容}private String getCurrentTime() {Date d = new Date();                      //创建当前日期对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");return sdf.format(d);                      //将时间格式化}public void centerPanel() {Panel center = new Panel();                    //创建中间的PanelviewText = new TextArea();sendText = new TextArea(5, 1);//Panel默认流式布局,而我们需要将两个文本区域一个放在Panel的南边,一个放在Panel的中间,应该用边界布局center.setLayout(new BorderLayout());     //设置为边界布局管理器center.add(sendText, BorderLayout.SOUTH);   //发送的文本区域放在南边center.add(viewText, BorderLayout.CENTER); //显示的文本区域放在中间viewText.setEditable(false);               //设置显示的文本区域不可以编辑viewText.setBackground(Color.WHITE);        //设置背景颜色 Color类中同一颜色有大写字段和小写字段两种,其实是一个东西。底层代码中,小写的静态常量被RGB三原色作为参数的Color对象赋值,大写的静态常量直接被小写的静态常量赋值。sendText.setFont(new Font("xxx", Font.PLAIN, 15));viewText.setFont(new Font("xxx", Font.PLAIN, 15));this.add(center, BorderLayout.CENTER);     //将Panel放在Frame的中间}public void southPanel() {Panel south = new Panel();                    //创建南边的Paneltf = 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);      //将Panel放在Frame的南边}public void init() {this.setLocation(500, 50);this.setSize(400, 600);try {socket = new DatagramSocket();            //一初始化就创建码头bw = new BufferedWriter(new FileWriter("config.txt", true));} catch (Exception e) {e.printStackTrace();}new Receive().start();                        //一初始化就开启接收,避免两条线程争抢执行权this.setVisible(true);}//内部定义一个内部类做接收端,方便调用外部类的方法(无论公有的还是私有的)private class Receive extends Thread {          //接收和发送需要同时执行,所以定义成多线程的public void run() {try {socket = new DatagramSocket(9999);DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);while(true) {socket.receive(packet);            //接收信息byte[] arr = packet.getData();       //获取字节数据int len = packet.getLength();      //获取有效的字节数据长度String message = new String(arr, 0, len);String time = getCurrentTime();     //获取当前时间String ip = packet.getAddress().getHostAddress();  //获取ip地址String str = time + " " + ip + " 对我说:\r\n" + message + "\r\n\r\n";viewText.append(str);bw.write(str);}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {new Demo4_GUIChat4();    //创建一个Frame的子类对象,即创建一个窗体出来}
}

UDP聊天震动功能

演示:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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;
/*** GUI聊天*/
public class Demo4_GUIChat4 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 bw;public Demo4_GUIChat4() {   //一创建子类对象,构造方法中的代码自动运行init();        //将代码抽取成一个方法,防止构造方法中的代码过于臃肿southPanel();centerPanel();event();}public void event() {this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {try {socket.close();                       //在退出java虚拟机之前关流bw.close();} catch (IOException e1) {e1.printStackTrace();}System.exit(0);}});send.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send();} catch (IOException e1) {e1.printStackTrace();}}});log.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {logFile();} catch (IOException e1) {e1.printStackTrace();}}});clear.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {viewText.setText("");}});shake.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send(new byte[]{-1}, tf.getText());} catch (IOException e1) {e1.printStackTrace();}}});}private void shake() {int x = this.getLocation().x;              //获取横坐标位置int y = this.getLocation().y;             //获取纵坐标位置for(int i = 0; i < 5; 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 {bw.flush();                                  //刷新缓冲区FileInputStream fis = new FileInputStream("config.txt");ByteArrayOutputStream baos = new ByteArrayOutputStream();    //在内存中创建缓冲区int len;byte[] arr = new byte[8192];while((len = fis.read(arr)) != -1) {baos.write(arr, 0, len);}String str = baos.toString();               //将内存中的内容转换成了字符串viewText.setText(str);fis.close();}private void send(byte[] arr, String ip) throws IOException {DatagramPacket packet = new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), 9999);socket.send(packet);                      //发送数据}private void send() throws IOException {     //send属于在主线程里跑 main() - 构造方法 - event() - send()String message = sendText.getText();        //获取发送区域的内容String ip = tf.getText();                   //获取ip地址send(message.getBytes(), ip);String time = getCurrentTime();               //获取当前时间String str = time + " 我对:" + ip + " 说\r\n" + message + "\r\n\r\n";  //Alt + Shift + L 抽取局部变量viewText.append(str);                         //将信息添加到显示区域中bw.write(str);sendText.setText("");                      //清除发送区域的内容}private String getCurrentTime() {Date d = new Date();                      //创建当前日期对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");return sdf.format(d);                      //将时间格式化}public void centerPanel() {Panel center = new Panel();                    //创建中间的PanelviewText = new TextArea();sendText = new TextArea(5, 1);//Panel默认流式布局,而我们需要将两个文本区域一个放在Panel的南边,一个放在Panel的中间,应该用边界布局center.setLayout(new BorderLayout());     //设置为边界布局管理器center.add(sendText, BorderLayout.SOUTH);   //发送的文本区域放在南边center.add(viewText, BorderLayout.CENTER); //显示的文本区域放在中间viewText.setEditable(false);               //设置显示的文本区域不可以编辑viewText.setBackground(Color.WHITE);        //设置背景颜色 Color类中同一颜色有大写字段和小写字段两种,其实是一个东西。底层代码中,小写的静态常量被RGB三原色作为参数的Color对象赋值,大写的静态常量直接被小写的静态常量赋值。sendText.setFont(new Font("xxx", Font.PLAIN, 15));viewText.setFont(new Font("xxx", Font.PLAIN, 15));this.add(center, BorderLayout.CENTER);     //将Panel放在Frame的中间}public void southPanel() {Panel south = new Panel();                    //创建南边的Paneltf = 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);      //将Panel放在Frame的南边}public void init() {this.setLocation(500, 50);this.setSize(400, 600);try {socket = new DatagramSocket();            //一初始化就创建码头bw = new BufferedWriter(new FileWriter("config.txt", true));} catch (Exception e) {e.printStackTrace();}new Receive().start();                        //一初始化就开启接收,避免两条线程争抢执行权this.setVisible(true);}//内部定义一个内部类做接收端,方便调用外部类的方法(无论公有的还是私有的)private class Receive extends Thread {          //接收和发送需要同时执行,所以定义成多线程的public void run() {try {socket = new DatagramSocket(9999);DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);while(true) {socket.receive(packet);            //接收信息byte[] arr = packet.getData();       //获取字节数据int len = packet.getLength();      //获取有效的字节数据长度if(arr[0] == -1 && len == 1) {     //如果发过来的数组第一个存储的值是1,并且数组长度是1shake();                        //调用震动方法continue;                       //终止本次循环,继续下次循环,因为震动后不需要执行下面的代码}String message = new String(arr, 0, len);String time = getCurrentTime();      //获取当前时间String ip = packet.getAddress().getHostAddress();  //获取ip地址String str = time + " " + ip + " 对我说:\r\n" + message + "\r\n\r\n";viewText.append(str);bw.write(str);}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {new Demo4_GUIChat4();    //创建一个Frame的子类对象,即创建一个窗体出来}
}

UDP聊天快捷键和代码优化

演示:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
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;
/*** GUI聊天*/
public class Demo4_GUIChat4 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 bw;public Demo4_GUIChat4() {   //一创建子类对象,构造方法中的代码自动运行init();        //将代码抽取成一个方法,防止构造方法中的代码过于臃肿southPanel();centerPanel();event();}public void event() {this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {try {socket.close();                       //在退出java虚拟机之前关流bw.close();} catch (IOException e1) {e1.printStackTrace();}System.exit(0);}});send.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send();} catch (IOException e1) {e1.printStackTrace();}}});log.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {logFile();} catch (IOException e1) {e1.printStackTrace();}}});clear.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {viewText.setText("");}});shake.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {try {send(new byte[]{-1}, tf.getText());} catch (IOException e1) {e1.printStackTrace();}}});sendText.addKeyListener(new KeyAdapter() {public void keyReleased(KeyEvent e) {
//              if(e.getKeyCode() == KeyEvent.VK_ENTER && e.isControlDown()) {    //isControlDown Ctrl键是否被按下if(e.getKeyCode() == KeyEvent.VK_ENTER) {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 < 5; 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 {bw.flush();                                  //刷新缓冲区FileInputStream fis = new FileInputStream("config.txt");ByteArrayOutputStream baos = new ByteArrayOutputStream();    //在内存中创建缓冲区int len;byte[] arr = new byte[8192];while((len = fis.read(arr)) != -1) {baos.write(arr, 0, len);}String str = baos.toString();               //将内存中的内容转换成了字符串viewText.setText(str);fis.close();}private void send(byte[] arr, String ip) throws IOException {DatagramPacket packet = new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), 9999);socket.send(packet);                      //发送数据}private void send() throws IOException {     //send属于在主线程里跑 main() - 构造方法 - event() - send()String message = sendText.getText();        //获取发送区域的内容String ip = tf.getText();                   //获取ip地址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);                         //将信息添加到显示区域中bw.write(str);sendText.setText("");                      //清除发送区域的内容}private String getCurrentTime() {Date d = new Date();                      //创建当前日期对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");return sdf.format(d);                      //将时间格式化}public void centerPanel() {Panel center = new Panel();                    //创建中间的PanelviewText = new TextArea();sendText = new TextArea(5, 1);//Panel默认流式布局,而我们需要将两个文本区域一个放在Panel的南边,一个放在Panel的中间,应该用边界布局center.setLayout(new BorderLayout());     //设置为边界布局管理器center.add(sendText, BorderLayout.SOUTH);   //发送的文本区域放在南边center.add(viewText, BorderLayout.CENTER); //显示的文本区域放在中间viewText.setEditable(false);               //设置显示的文本区域不可以编辑viewText.setBackground(Color.WHITE);        //设置背景颜色 Color类中同一颜色有大写字段和小写字段两种,其实是一个东西。底层代码中,小写的静态常量被RGB三原色作为参数的Color对象赋值,大写的静态常量直接被小写的静态常量赋值。sendText.setFont(new Font("xxx", Font.PLAIN, 15));viewText.setFont(new Font("xxx", Font.PLAIN, 15));this.add(center, BorderLayout.CENTER);     //将Panel放在Frame的中间}public void southPanel() {Panel south = new Panel();                    //创建南边的Paneltf = 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);      //将Panel放在Frame的南边}public void init() {this.setLocation(500, 50);this.setSize(400, 600);try {socket = new DatagramSocket();            //一初始化就创建码头bw = new BufferedWriter(new FileWriter("config.txt", true));} catch (Exception e) {e.printStackTrace();}new Receive().start();                        //一初始化就开启接收,避免两条线程争抢执行权this.setVisible(true);}//内部定义一个内部类做接收端,方便调用外部类的方法(无论公有的还是私有的)private class Receive extends Thread {          //接收和发送需要同时执行,所以定义成多线程的public void run() {try {socket = new DatagramSocket(9999);DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);while(true) {socket.receive(packet);            //接收信息byte[] arr = packet.getData();       //获取字节数据int len = packet.getLength();      //获取有效的字节数据长度if(arr[0] == -1 && len == 1) {     //如果发过来的数组第一个存储的值是1,并且数组长度是1shake();                        //调用震动方法continue;                       //终止本次循环,继续下次循环,因为震动后不需要执行下面的代码}String message = new String(arr, 0, len);String time = getCurrentTime();      //获取当前时间String ip = packet.getAddress().getHostAddress();  //获取ip地址String str = time + " " + ip + " 对我说:\r\n" + message + "\r\n\r\n";viewText.append(str);bw.write(str);}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {new Demo4_GUIChat4();    //创建一个Frame的子类对象,即创建一个窗体出来}
}

UDP聊天生成jar文件

右键项目文件 - Import... - 选择Java文件夹中的JAR file选项 点Next > - 确认是不是你选中的原文件 - 在Select the export destination:中选择生成的地方 - 不是直接点Finish 接着点Next > - 再点Next > - 在Select the class of the application entry point:中选择刚才那个类 然后点Finish - 在弹出的提示中选OK(网上基本也是这种方法,但我失败了= _ =!!)


TCP协议

客户端

创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器。

调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流。

输入流可以读取服务端输出流写出的数据。

输出流可以写出数据到服务端的输入流。

演示:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;/*** 客户端*/
public class Demo1_Client {public static void main(String[] args) throws UnknownHostException, IOException {Socket socket = new Socket("127.0.0.1", 12345);InputStream is = socket.getInputStream();        //获取客户端的输入流OutputStream os = socket.getOutputStream();     //获取客户端的输出流 byte[] arr = new byte[1024];int len = is.read(arr);                           //读取服务器发过来的数据System.out.println(new String(arr, 0, len));   //将数据转换成字符串并打印os.write("学习挖掘机数据哪家强?".getBytes());      //客户端向服务器写数据socket.close();}
}

服务端

创建ServerSocket(需要指定端口号)。

调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket。

调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流。

输入流可以读取客户端输出流写出的数据。

输出流可以写出数据到客户端的输入流。

演示:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 服务端*/
public class Demo2_Server {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(12345);Socket socket = server.accept();          //接受客户端的请求InputStream is = socket.getInputStream();    //获取服务端的输入流OutputStream os = socket.getOutputStream(); //获取服务端的输出流 os.write("百度一下你就知道".getBytes());          //服务器向客户端写出数据byte[] arr = new byte[1024];int len = is.read(arr);                          //读取客户端发过来的数据System.out.println(new String(arr, 0, len));   //将数据转换成字符串并打印socket.close();}
}

TCP协议代码优化

客户端 演示:i

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;/*** 客户端*/
public class Demo2_Client2 {public static void main(String[] args) throws UnknownHostException, IOException {Socket socket = new Socket("127.0.0.1", 12345);BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));     //将字节流包装成了字符流PrintStream ps = new PrintStream(socket.getOutputStream());           //PrintStream中有写出换行的的方法ps.println("Hello~ 酷狗");System.out.println(br.readLine());ps.println("淦,我还以为你想开QQ音乐呢");System.out.println(br.readLine());socket.close();}
}

服务端 演示:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 服务端*/
public class Demo2_Server2 {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(12345);Socket socket = server.accept();         //接受客户端的请求BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));      //将字节流包装成了字符流PrintStream ps = new PrintStream(socket.getOutputStream());           //PrintStream中有写出换行的的方法System.out.println(br.readLine());           //br.readLine()在读的的时候以判断\r\n为结束标记的。如果客户端在写入消息时用print而不是println。则读取不会结束,下一句也不会写入。因此,客户端也无法读取,客户端的下一句也无法写入。程序会僵持住ps.println("对不起,我想开的是网易云音乐,点错了~");System.out.println(br.readLine());ps.println("一起来网易云听音乐吧,这里的听众有各种各样公司的程序员");socket.close();}
}

服务端是多线程的

演示:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 服务端*/
public class Demo2_Server2 {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(12345);while(true) {final Socket socket = server.accept();          //接受客户端的请求new Thread() {public void run() {try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));        //将字节流包装成了字符流PrintStream ps = new PrintStream(socket.getOutputStream());           //PrintStream中有写出换行的的方法System.out.println(br.readLine());           ps.println("对不起,我想开的是网易云音乐,点错了~");System.out.println(br.readLine());ps.println("一起来网易云听音乐吧,这里的听众有各种各样公司的程序员");socket.close();} catch (IOException e) {e.printStackTrace();}}}.start();}}
}

网络编程练习一

客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串。

客户端演示:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;public class Test1_Client {/*** 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串。* @param args* @throws IOException * @throws UnknownHostException */public static void main(String[] args) throws UnknownHostException, IOException {Scanner sc = new Scanner(System.in);           //创建键盘录入对象Socket socket = new Socket("127.0.0.1", 54321);    //创建客户端,指定ip地址和端口号BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));   //获取输入流PrintStream ps = new PrintStream(socket.getOutputStream());     //获取输出流ps.println(sc.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 IOException {ServerSocket server = new ServerSocket(54321);System.out.println("服务器启动,绑定54321端口");while(true) {/*final*/ Socket socket = server.accept(); //接受客户端的请求  不加final也行,应该是版本更新后改了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();           //将字符串转换成StringBuilder再进行反转再重新转换成字符串ps.println(line);               //反转后写回去socket.close();     //Socket类的close()中写到:关闭此套接字也将会关闭套接字的InputStream和OutputStream. 所以br和ps不用单独关.} catch (IOException e) {e.printStackTrace();}}}.start();}}
}

网络编程练习二

客户端向服务器上传文件。

客户端演示:

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 Demo2_UpdateServer {public static void main(String[] args) throws IOException {//3.建立多线程的服务器ServerSocket server = new ServerSocket(12345);System.out.println("服务器启动,绑定12345端口号");//4.读取文件名while(true) {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();//5.判断文件是否存在,将结果发回客户端File dir = new File("update");dir.mkdir();                        //创建文件夹File file = new File(dir, fileName);//封装成File对象if(file.exists()) {                  //如果服务器已经存在这个文件ps.println("存在");              //将存在写给客户端socket.close();               //关闭socketreturn;}else {ps.println("不存在");}//8.定义FileOutputStream,从网络读取数据,存储到本地FileOutputStream fos = new FileOutputStream(file);byte[] arr = new byte[8192];int len;while((len = is.read(arr)) != -1) {fos.write(arr, 0, len);}fos.close();socket.close();} catch (IOException e) {e.printStackTrace();}}}.start();}}
}

服务端演示:

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 Demo2_UpdateServer {public static void main(String[] args) throws IOException {//3.建立多线程的服务器ServerSocket server = new ServerSocket(12345);System.out.println("服务器启动,绑定12345端口号");//4.读取文件名while(true) {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();//5.判断文件是否存在,将结果发回客户端File dir = new File("update");dir.mkdir();                        //创建文件夹File file = new File(dir, fileName);//封装成File对象if(file.exists()) {                  //如果服务器已经存在这个文件ps.println("存在");              //将存在写给客户端socket.close();               //关闭socketreturn;}else {ps.println("不存在");}//8.定义FileOutputStream,从网络读取数据,存储到本地FileOutputStream fos = new FileOutputStream(file);byte[] arr = new byte[8192];int len;while((len = is.read(arr)) != -1) {fos.write(arr, 0, len);}fos.close();socket.close();} catch (IOException e) {e.printStackTrace();}}}.start();}}
}

Java 知识点整理-20.网络编程相关推荐

  1. Java并发编程实战_阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

    前言 为了帮助初级开发者快速掌握高并发.网络编程.微服务.海量数据的处理这些实用技术,本文以"理论+范例"的形式对各个知识点进行了详细的讲解,力争让读者在实践中快速掌握相关知识. ...

  2. 阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

    前言 有人调侃我们说: 程序员不如送外卖.送外卖是搬运食物,自己是搬运代码,都不产出新的东西-- 透支体力,又消耗健康,可替代性极强,30岁之后就要面临被优化的危险-- 想跳槽,但是更高的平台难进,同 ...

  3. Java学习——Day14:网络编程

    7.1 网络编程概述 Java是 Internet 上的语言,它从语言级上提供了对网络应用程 序的支持,程序员能够很容易开发常见的网络应用程序. Java提供的网络类库,可以实现无痛的网络连接,联网的 ...

  4. 20165310 Java实验五《网络编程与安全》

    20165310 Java实验五<网络编程与安全> 任务一 题目:①编写MyBC.java实现中缀表达式转后缀表达式的功能:②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表 ...

  5. Java语言进阶:网络编程入门

    Java语言进阶:网络编程 网络编程入门 C/S C/S结构 :全称为Client/Server结构,是指客户端和服务器结构.常见程序有QQ.迅雷等软件. 特点: 客户端和服务器是分开的,需要下载客户 ...

  6. 《亿级流量JAVA高并发与网络编程实战》笔记--------更新中

    <亿级流量JAVA高并发与网络编程实战>笔记 第一章 高并发概述 "高并发技术" 是一个广义的概念,是指一种高效的地实现并发需求的解决方案,是技术领域的名称,可以包含架 ...

  7. 大数据——Java 知识点整理

    1. JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java开发工具包,提供了java的开发环境和运行环境. JRE:Java Runtime Envir ...

  8. Linux C++/Java/Web/OC Socket网络编程

    一,Linux C++ Socket网络编程 1.什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制 ...

  9. Java基础篇:网络编程

    文章目录 概述 通信要素之一:IP和端口号 通信要素之二:网络协议 TCP网络编程 UDP网络编程 URL编程 总结 概述 Java是 Internet 上的语言,它从语言级上提供了对网络应用程序的支 ...

最新文章

  1. JS栈结构的简单封装
  2. 能“预测未来”的AI来了!谷歌DeepMind推Dreamer,训练时间减半
  3. java数组赋值语句,稳进大厂
  4. iOS序列化与反序列化
  5. Spring MVC 中自定义视图 @Component 及 配置 多个视图解析器 Excel视图
  6. jquery1.9 下检测浏览器类型和版本
  7. 官宣,11月8号,.NET6+64位VS璀璨面世!
  8. 关于Mac重启之后壁纸总是恢复默认的解决办法
  9. memcache获取所有内存数据
  10. 《HTML与CSS入门经典(第8版)》——第2章 发布Web内容2.1 创建用于本章的示例文件...
  11. java JDK1.8中文手册
  12. CSS3实现DIV圆角完整代码
  13. windows10服务器iis发布网站,win10系统+iis7发布网站或服务的详细办法
  14. 密度图与等高线图——Note_5
  15. vscode html 英文感叹号(!+ tap)快速模板 骨架 无法使用 替代办法
  16. 台式计算机使用寿命,惠普台式电脑怎么样(深度评测其质量及使用寿命)
  17. RPA技术在提升业务合规操作方面的作用及相关风险探讨
  18. 8051单片机基础1:8051的起源
  19. 自己动手丰衣足食之移动端日期选择插件(强烈推荐)
  20. 我国计算机在办公应用普及时间,论如何提高水利工程中计算机的应用

热门文章

  1. Multiple histogram-based face recognition with high speed FPGA implementation
  2. License for package Android SDK Build-Tools 28.0.3 not accepted【解决】
  3. 写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。
  4. GPIO模式运用场合详解
  5. GDKOI2018战记
  6. kali渗透测试(2)
  7. JAVA计算机毕业设计病人跟踪治疗信息管理系统演示2021Mybatis+源码+数据库+lw文档+系统+调试部署
  8. PyDev:修改代码模板自动添加encoding=utf8,避免中文乱码
  9. win10电脑发现不了华为share_华为手机显示Win10计算机,并一直显示要投影的解决方案...
  10. wps mysql ubuntu_Ubuntu16.04 安装 wps (不推荐安装)