第二十六天????414
1:网络编程(理解)????414
(1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享????414
(2)网络编程模型????414
(3)网络编程的三要素????414
(4)网络编程中主要类介绍:????416
A:InetAddress: 此类表示互联网协议 (IP) 地址。????416
B:????UDP协议下的Socket对象类DatagramSocket????418
1.发送端:????418
2.接收端:????419
C:????TCP协议下的主要类介绍:????420
(5)Socket机制????423
(4)UDP协议发送和接收数据(掌握)????423
1.原理图解????423
2.发送:步骤????423
3.接收:步骤????424
(5)TCP协议发送和接收数据(掌握)????425
A:原理图解????425
2.发送:步骤????425
3.接收:步骤????427
(6)案例:????427
A:UDP????428
a:最基本的UDP协议发送和接收数据????428
b:把发送数据改进为键盘录入????429
c:一个简易聊天小程序并用多线程改进????431
B:TCP????433
a: 服务器给出反馈????433
c:客户端键盘录入服务器控制台输出????435
d:客户端键盘录入服务器写到文本文件????437
e:客户端读取文本文件服务器控制台输出????438
f:客户端读取文本文件服务器写到文本文件????440
g:上传图片????443
h:多线程改进上传文件????445
?
?
?
第二十六天
1:网络编程(理解)
????(1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享
????(2)网络编程模型
????(3)网络编程的三要素
????????A:IP地址
????????????a:点分十进制
????????????b:IP地址的组成
????????????c:IP地址的分类
????????????d:dos命令
????????????e:InetAddress
????????B:端口
????????????是应用程序的标识。范围:0-65535。其中0-1024不建议使用。
????????C:协议
????????????UDP:数据打包,有限制,不连接,效率高,不可靠
????????????TCP:建立数据通道,无限制,效率低,可靠
/* * 网络编程三要素: ????A:IP地址 ????B:端口 ????C:协议 ???? 举例: ????我想和林青霞说话了。肿么办? ????A:我要找到林青霞。 ????B:对她说话,要对耳朵说。 ????C:我说什么呢?"I Love You" ???? 但是,她没学过英语,听不懂。 ???? 我没必要说英语,说汉语就可以了:我爱你 ???? IP地址: ????网络中计算机的唯一标识。 ???? ????计算机只能识别二进制的数据,所以我们的IP地址应该是一个二进制的数据。 ????但是呢,我们配置的IP地址确不是二进制的,为什么呢? ????????IP:192.168.1.100 ????????换算:11000000 10101000 00000001 01100100 ????假如真是:11000000 10101000 00000001 01100100的话。 ????我们如果每次再上课的时候要配置该IP地址,记忆起来就比较的麻烦。 ????所以,为了方便表示IP地址,我们就把IP地址的每一个字节上的数据换算成十进制,然后用.分开来表示: ????????"点分十进制" ???????? ????IP地址的组成:网络号段+主机号段 ????????A类:第一号段为网络号段+后三段的主机号段 ????????????一个网络号:256*256*256 = 16777216 ????????B类:前二号段为网络号段+后二段的主机号段 ????????????一个网络号:256*256 = 65536 ????????C类:前三号段为网络号段+后一段的主机号段 ????????????一个网络号:256 ???? ????IP地址的分类: ????????A类????1.0.0.1---127.255.255.254????(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)????????????????????????????(2)127.X.X.X是保留地址,用做循环测试用的。 ????????B类????128.0.0.1---191.255.255.254????172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。 ????????C类????192.0.0.1---223.255.255.254????192.168.X.X是私有地址 ????????D类????224.0.0.1---239.255.255.254 ???? ????????E类????240.0.0.1---247.255.255.254 ???????? ????两个DOS命令: ????????ipconfig ????????ping 后面跟ip地址。测试本机与指定的ip地址间的通信是否有问题 ???????? ????特殊的IP地址: ????????127.0.0.1 回环地址(表示本机) ????????x.x.x.255 广播地址 ????????x.x.x.0 网络地址 ???????? 端口号: ????正在运行的程序的标识。 ????有效端口:0~65535,其中0~1024系统使用或保留端口。 ???? 协议: ????通信的规则 ???? ????UDP: ????????把数据打包 ????????数据有限制 ????????不建立连接 ????????速度快 ????????不可靠 ???? ????TCP: ????????建立连接通道 ????????数据无限制 ????????速度慢 ????????可靠 ???? ????举例: ????????UDP:发短信 ????????TCP:打电话 */ |
?
????(4)网络编程中主要类介绍:
????????A:InetAddress: 此类表示互联网协议 (IP) 地址。
????????????构造方法:
????????????public
static InetAddress getByName(String host):根据主机名或者ip地址
????????????的字符串表现形式创建IP地址对象
????????????普通方法:
????????????public String getHostName():获取主机名
????????????public String getHostAddress():获取IP地址
????????????案例演示:
import java.net.InetAddress; import java.net.UnknownHostException; ? /* * 如果一个类没有构造方法: * A:成员全部是静态的(Math,Arrays,Collections) * B:单例设计模式(Runtime) * C:类中有静态方法返回该类的对象(InetAddress) * ????????class Demo { * ????????????private Demo(){} * * ????????????public static Demo getXxx() { * ????????????????return new Demo(); * ????????????} * ????????} * * 看IP地址类:InetAddress的成员方法: * public static InetAddress getByName(String host): * ????????????????????根据主机名或者IP地址的字符串表示得到IP地址对象 * * ????????普通方法: * ???????? public String getHostName():获取该IP地址对象的主机名 * ???????? public String getHostAddress():获取主机IP地址 */ public?class InetAddressDemo { ????public?static?void main(String[] args) throws UnknownHostException { ????????// public static InetAddress getByName(String host) ????????// InetAddress address = InetAddress.getByName("liuyi"); ????????// InetAddress address = InetAddress.getByName("192.168.12.92"); ????????InetAddress address = InetAddress.getByName("asus"); ? ????????// 获取两个东西:主机名,IP地址 ????????// public String getHostName() ????????String name = address.getHostName(); ????????// public String getHostAddress() ????????String ip = address.getHostAddress(); ????????System.out.println(name + "---" + ip); ????} } |
?
????
?
????????B:????UDP协议下的Socket对象类DatagramSocket
????????????1.发送端:
?
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * UDP协议发送数据: * A:创建发送端Socket对象 * B:创建数据,并把数据打包 * C:调用Socket对象的发送方法发送数据包 * D:释放资源 * * 说明:UDP协议下的接收端和发送端的Socket对象都是同一个类DatagramSocket * ???? * ????DatagramSocket类的方法: * ????????构造方法:public DatagramSocket() * ????????普通方法:public void send(DatagramPacket p): * ????????????????从此套接字发送数据报包 * ???????????? public void close() * ????????????????关闭此数据报套接字。 * ???????????? public synchronized void receive(DatagramPacket p): * ???????????????? 从此套接字接收数据报包。 * ???????????????? * ????DatagramPacket数据包类: * ????????构造方法:public DatagramPacket(byte buf[], int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号???? ? public DatagramPacket(byte buf[], int length): ????????构造 DatagramPacket,用来接收长度为 length 的数据包 ? public synchronized InetAddress getAddress(): ????????????????返回某台机器的 IP 地址对象 ???????????????? public synchronized byte[] getData():返回数据缓冲区 public synchronized int getLength():返回将要发送或接收到的数据的长度 */ public?class SendDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建发送端Socket对象 ????????// DatagramSocket() ????????DatagramSocket ds = new DatagramSocket(); ? ????????// 创建数据,并把数据打包 ????????// DatagramPacket(byte[] buf, int length, InetAddress address, int port) ????????// 创建数据 ????????byte[] bys = "hello,udp,我来了".getBytes(); ????????// 长度 ????????int?length = bys.length; ????????// IP地址对象 ????????InetAddress address = InetAddress.getByName("192.168.12.92"); ????????// 端口 ????????int?port = 10086; ????????DatagramPacket dp = new DatagramPacket(bys, length, address, port); ? ????????// 调用Socket对象的发送方法发送数据包 ????????// public void send(DatagramPacket p) ????????ds.send(dp); ? ????????// 释放资源 ????????ds.close(); ????} } |
?
????????????2.接收端:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; ? /* * UDP协议接收数据: * A:创建接收端Socket对象 * B:创建一个数据包(接收容器) * C:调用Socket对象的接收方法接收数据 * D:解析数据包,并显示在控制台 * E:释放资源 */ public?class ReceiveDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建接收端Socket对象 ????????// DatagramSocket(int port) ????????DatagramSocket ds = new DatagramSocket(10086); ? ????????// 创建一个数据包(接收容器) ????????// DatagramPacket(byte[] buf, int length) ????????byte[] bys = new?byte[1024]; ????????int?length = bys.length; ????????DatagramPacket dp = new DatagramPacket(bys, length); ? ????????// 调用Socket对象的接收方法接收数据 ????????// public void receive(DatagramPacket p) ????????ds.receive(dp); // 阻塞式 ? ????????// 解析数据包,并显示在控制台 ????????// 获取对方的ip ????????// public InetAddress getAddress() ????????InetAddress address = dp.getAddress(); ????????String ip = address.getHostAddress(); ????????// public byte[] getData():获取数据缓冲区 ????????// public int getLength():获取数据的实际长度 ????????byte[] bys2 = dp.getData(); ????????int?len = dp.getLength(); ????????String s = new String(bys2, 0, len); ????????System.out.println(ip + "传递的数据是:" + s); ? ????????// 释放资源 ????????ds.close(); ????} } |
?
????????C:????TCP协议下的主要类介绍:
????????????客户端的主要类:Socket类
????????????????构造方法
public Socket(String host, int
port):创建一个流套接字并将其连接到指定主机上的指定端口号。
普通方法:
public OutputStream getOutputStream():返回此套接字的输出流。
public InputStream getInputStream():返回此套接字的输入流
?
public
synchronized
void close():关闭此套接字
?
????????????服务器端的主要类:ServerSocket类
????????????????构造方法
????????????????public ServerSocket(int
port):创建绑定到特定端口的服务器套接字
?
????????????????普通方法
????????????????public Socket accept():侦听并接受到此套接字的连接
????????????????
????????????????案例演示:
????????????????1.客户端:
import java.io.IOException; import?java.io.InputStream; import java.io.OutputStream; import java.net.Socket; ? /* * TCP协议发送数据: * A:创建发送端的Socket对象 * ????????这一步如果成功,就说明连接已经建立成功了。 * B:获取输出流,写数据 * C:释放资源 * * ????TCP协议下的套接字类: * ????????套接字类:发送端的socket * ????????????构造方法:public Socket(String host, int port) * ????????????????????创建一个流套接字并将其连接到指定主机上的指定端口号。 * ????????????普通方法: * ????????????public OutputStream getOutputStream(): * ????????????????????????????????返回此套接字的输出流。 * ????????????public InputStream getInputStream(): * ????????????????????????????????返回此套接字的输入流 * * ????????????public synchronized void close():关闭此套接字 * * * 连接被拒绝。TCP协议一定要先看服务器。 * java.net.ConnectException: Connection refused: connect */ public?class ClientDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建发送端的Socket对象 ????????// Socket(InetAddress address, int port) ????????// Socket(String host, int port) ????????// Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888); ????????Socket s = new Socket("192.168.12.92", 8888); ? ????????// 获取输出流,写数据 ????????// public OutputStream getOutputStream() ????????OutputStream os = s.getOutputStream(); ????????os.write("hello,tcp,我来了".getBytes()); ? ????????// 释放资源 ????????s.close(); ????} } |
?
????????????????2.服务器端:????????????????
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; ? /* * TCP协议接收数据: * A:创建接收端的Socket对象 * B:监听客户端连接。返回一个对应的Socket对象 * C:获取输入流,读取数据显示在控制台 * D:释放资源 * * 服务器端的套接字类:ServerSocket * ????????构造方法: * ????????public ServerSocket(int port):创建绑定到特定端口的服务器套接字 * * ????????普通方法: * ????????public Socket accept():侦听并接受到此套接字的连接 * 说明:不应该关闭服务器端的套接字连接 */ public?class ServerDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建接收端的Socket对象 ????????// ServerSocket(int port) ????????ServerSocket ss = new ServerSocket(8888); ? ????????// 监听客户端连接。返回一个对应的Socket对象 ????????// public Socket accept() ????????Socket s = ss.accept(); // 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。 ? ????????// 获取输入流,读取数据显示在控制台 ????????InputStream is = s.getInputStream(); ? ????????byte[] bys = new?byte[1024]; ????????int?len = is.read(bys); // 阻塞式方法 ????????String str = new String(bys, 0, len); ? ????????String ip = s.getInetAddress().getHostAddress(); ? ????????System.out.println(ip + "---" + str); ? ????????// 释放资源 ????????s.close(); ????????// ss.close(); //这个不应该关闭 ????} } |
?
????(5)Socket机制
????????A:通信两端都应该有Socket对象
????????B:所有的通信都是通过Socket间的IO进行操作的
????(4)UDP协议发送和接收数据(掌握)
????????1.原理图解
????????2.发送:步骤
????????????A:创建UDP发送端的Socket对象
????????????B:创建数据并把数据打包
????????????C:发送数据
????????????D:释放资源
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * 发送端: */ public?class SendDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建发送端的Socket对象 ????????DatagramSocket ds = new DatagramSocket(); ? ????????// 创建数据并打包 ????????byte[] bys = "helloworld".getBytes(); ????????DatagramPacket dp = new DatagramPacket(bys, bys.length, ????????????????InetAddress.getByName("192.168.12.92"), 12345); ? ????????// 发送数据 ????????ds.send(dp); ? ????????// 释放资源 ????????ds.close(); ????} } |
?
????????????
????????3.接收:步骤
????????????A:创建UDP接收端的Socket对象
????????????B:创建数据包用于接收数据
????????????C:接收数据
????????????D:解析数据包
????????????E:释放资源
/* * 多次启动接收端: * ????????java.net.BindException: Address already in use: Cannot bind * ????????端口被占用。 */ public?class ReceiveDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建接收端的Socket对象 ????????DatagramSocket ds = new DatagramSocket(12345); ? ????????// 创建一个包裹 ????????byte[] bys = new?byte[1024]; ????????DatagramPacket dp = new DatagramPacket(bys, bys.length); ? ????????// 接收数据 ????????ds.receive(dp); ? ????????// 解析数据 ????????String ip = dp.getAddress().getHostAddress(); ????????String s = new String(dp.getData(), 0, dp.getLength()); ????????System.out.println("from " + ip + " data is : " + s); ? ????????// 释放资源 ????????ds.close(); ????} } |
?
????(5)TCP协议发送和接收数据(掌握)
????????A:原理图解
????????
?
????????2.发送:步骤
????????????a.创建TCP客户端的Socket对象
????????????b.获取输出流,写数据
????????????c.释放资源
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /* * 客户端: */ public?class ClientDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("192.168.12.92", 9999); ? ????????// 获取输出流 ????????OutputStream os = s.getOutputStream(); ????????os.write("今天天气很好,适合睡觉".getBytes()); ? ????????// 获取输入流 ????????InputStream is = s.getInputStream(); ????????byte[] bys = new?byte[1024]; ????????int?len = is.read(bys);// 阻塞 ????????String client = new String(bys, 0, len); ????????System.out.println("client:" + client); ? ????????// 释放资源 ????????s.close(); ????} } |
?
????????????
????????3.接收:步骤
????????????A:创建TCP服务器端的Socket对象
????????????B:监听客户端连接
????????????C:获取输入流,读取数据
????????????D:释放资源
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class ServerDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(9999); ? ????????// 监听客户端的连接 ????????Socket s = ss.accept(); // 阻塞 ? ????????// 获取输入流 ????????InputStream is = s.getInputStream(); ????????byte[] bys = new?byte[1024]; ????????int?len = is.read(bys); // 阻塞 ????????String server = new String(bys, 0, len); ????????System.out.println("server:" + server); ? ????????// 获取输出流 ????????OutputStream os = s.getOutputStream(); ????????os.write("数据已经收到".getBytes()); ? ????????// 释放资源 ????????s.close(); ????????// ss.close(); ????} } |
?
????(6)案例:
????????A:UDP
????????????a:最基本的UDP协议发送和接收数据
????????????1.发送端
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * 发送端: */ public?class SendDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建发送端的Socket对象 ????????DatagramSocket?ds = new DatagramSocket(); ? ????????// 创建数据并打包 ????????byte[] bys = "helloworld".getBytes(); ????????DatagramPacket dp = new DatagramPacket(bys, bys.length, ????????????????InetAddress.getByName("192.168.12.92"), 12345); ? ????????// 发送数据 ????????ds.send(dp); ? ????????// 释放资源 ????????ds.close(); ????} } |
?
?
????????????2.接收端:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; ? /* * 多次启动接收端: * ????????java.net.BindException: Address already in use: Cannot bind * ????????端口被占用。 */ public?class ReceiveDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建接收端的Socket对象 ????????DatagramSocket ds = new DatagramSocket(12345); ? ????????// 创建一个包裹 ????????byte[] bys = new?byte[1024]; ????????DatagramPacket dp = new DatagramPacket(bys, bys.length); ? ????????// 接收数据 ????????ds.receive(dp); ? ????????// 解析数据 ????????String ip = dp.getAddress().getHostAddress(); ????????String s = new String(dp.getData(), 0, dp.getLength()); ????????System.out.println("from " + ip + " data is : " + s); ? ????????// 释放资源 ????????ds.close(); ????} } |
?
????????????b:把发送数据改进为键盘录入
????????????1.发送端
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; ? /* * 需求:数据来自于键盘录入 * 键盘录入数据要自己控制录入结束。 */ public?class SendDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建发送端的Socket对象 ????????DatagramSocket ds = new DatagramSocket(); ? ????????// 封装键盘录入数据 ????????BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????if ("886".equals(line)) { ????????????????break; ????????????} ? ????????????// 创建数据并打包 ????????????byte[] bys = line.getBytes(); ????????????// DatagramPacket dp = new DatagramPacket(bys, bys.length, ????????????// InetAddress.getByName("192.168.12.92"), 12345); ????????????DatagramPacket dp = new DatagramPacket(bys, bys.length, ????????????????????InetAddress.getByName("192.168.12.255"), 12345); ? ????????????// 发送数据 ????????????ds.send(dp); ????????} ? ????????// 释放资源 ????????ds.close(); ????} } |
?
?
????????????2.接收端:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; ? /* * 多次启动接收端: * ????????java.net.BindException: Address already in use: Cannot bind * ????????端口被占用。 */ public?class?ReceiveDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建接收端的Socket对象 ????????DatagramSocket ds = new DatagramSocket(12345); ? ????????while (true) { ????????????// 创建一个包裹 ????????????byte[] bys = new?byte[1024]; ????????????DatagramPacket dp = new DatagramPacket(bys, bys.length); ? ????????????// 接收数据 ????????????ds.receive(dp); ? ????????????// 解析数据 ????????????String ip = dp.getAddress().getHostAddress(); ????????????String s = new String(dp.getData(), 0, dp.getLength()); ????????????System.out.println("from " + ip + " data is : " + s); ????????} ? ????????// 释放资源 ????????// 接收端应该一直开着等待接收数据,是不需要关闭 ????????// ds.close(); ????} } |
?
?
????????????c:一个简易聊天小程序并用多线程改进
????????????1.发送端,实现多线程
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * 发送端:实现多线程 */ public?class SendThread implements Runnable { ? ????private DatagramSocket ds; ? ????public SendThread(DatagramSocket ds) { ????????this.ds = ds; ????} ? ????@Override ????public?void run() { ????????try { ????????????// 封装键盘录入数据 ????????????BufferedReader br = new BufferedReader(new InputStreamReader( ????????????????????System.in)); ????????????String line = null; ????????????while ((line = br.readLine()) != null) { ????????????????if ("886".equals(line)) { ????????????????????break; ????????????????} ? ????????????????// 创建数据并打包 ????????????????byte[] bys = line.getBytes(); ????????????????// DatagramPacket dp = new DatagramPacket(bys, bys.length, ????????????????// InetAddress.getByName("192.168.12.92"), 12345); ????????????????DatagramPacket dp = new DatagramPacket(bys, bys.length, ????????????????????????InetAddress.getByName("192.168.12.255"), 12306); ? ????????????????// 发送数据 ????????????????ds.send(dp); ????????????} ? ????????????// 释放资源 ????????????ds.close(); ????????} catch (IOException e) { ????????????e.printStackTrace(); ????????} ????} ? } |
?
?
????????????2.接收端,实现多线程
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; /* *接收端:实现多线程 */ public?class ReceiveThread implements Runnable { ????private DatagramSocket ds; ? ????public ReceiveThread(DatagramSocket ds) { ????????this.ds = ds; ????} ? ????@Override ????public?void run() { ????????try { ????????????while (true) { ????????????????// 创建一个包裹 ????????????????byte[] bys = new?byte[1024]; ????????????????DatagramPacket dp = new DatagramPacket(bys, bys.length); ? ????????????????// 接收数据 ????????????????ds.receive(dp); ? ????????????????// 解析数据 ????????????????String ip = dp.getAddress().getHostAddress(); ????????????????String s = new String(dp.getData(), 0, dp.getLength()); ????????????????System.out.println("from " + ip + " data is : " + s); ????????????} ????????} catch (IOException e) { ????????????e.printStackTrace(); ????????} ????} ? } |
?
????????????3.测试类
import java.io.IOException; import java.net.DatagramSocket; ? /* * 测试类:通过多线程改进刚才的聊天程序,这样我就可以实现在一个窗口发送和接收数据了 */ public?class ChatRoom { ????public?static?void main(String[] args) throws IOException { ????????//创建发送端Socket对象 ????????DatagramSocket dsSend = new DatagramSocket(); ????????//创建接收端Socket对象 ????????DatagramSocket dsReceive = new DatagramSocket(12306); ????????//创建发送线程对象 ????????SendThread st = new SendThread(dsSend); ????????//创建接收线程对象 ????????ReceiveThread rt = new ReceiveThread(dsReceive); ? ????????Thread t1 = new Thread(st); ????????Thread t2 = new Thread(rt); ????????//启动线程 ????????t1.start(); ????????t2.start(); ????} } |
?
????????B:TCP
????????????a: 服务器给出反馈
????????????1.客户端
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /* * 客户端: */ public?class ClientDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("192.168.12.92", 9999); ? ????????// 获取输出流 ????????OutputStream os = s.getOutputStream(); ????????os.write("今天天气很好,适合睡觉".getBytes()); ? ????????// 获取输入流 ????????InputStream is = s.getInputStream(); ????????byte[] bys = new?byte[1024]; ????????int?len = is.read(bys);// 阻塞 ????????String client = new String(bys, 0, len); ????????System.out.println("client:" + client); ? ????????// 释放资源 ????????s.close(); ????} } |
?
?
????????????2.服务器端:
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class ServerDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(9999); ? ????????// 监听客户端的连接 ????????Socket s = ss.accept(); // 阻塞 ? ????????// 获取输入流 ????????InputStream is = s.getInputStream(); ????????byte[] bys = new?byte[1024]; ????????int?len = is.read(bys); // 阻塞 ????????String server = new String(bys, 0, len); ????????System.out.println("server:" + server); ? ????????// 获取输出流 ????????OutputStream os = s.getOutputStream(); ????????os.write("数据已经收到".getBytes()); ? ????????// 释放资源 ????????s.close(); ????????// ss.close(); ????} } |
?
?
????????????c:客户端键盘录入服务器控制台输出
????????????1.客户端
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; ? /* * 需求:客户端键盘录入,服务器输出到控制台 */ public?class ClientDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("127.0.0.1", 22223); ? ????????// 键盘录入数据 ????????BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); ????????// 把通道内的流给包装一下 ????????BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( ????????????????s.getOutputStream())); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????// 键盘录入数据要自定义结束标记 ????????????if ("886".equals(line)) { ????????????????break; ????????????} ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ? ????????// 释放资源 ????????// bw.close();//不需要关闭 ????????// br.close();//不需要关闭 ????????s.close(); ????} } |
?
?
????????????2.服务器端:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class ServerDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(22223); ? ????????// 监听客户端连接 ????????Socket s = ss.accept(); ? ????????// 包装通道内容的流 ????????BufferedReader br = new BufferedReader(new InputStreamReader( ????????????????s.getInputStream())); ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????System.out.println(line); ????????} ? ????????// br.close(); ????????s.close(); ????????// ss.close(); ????} } |
?
????????????d:客户端键盘录入服务器写到文本文件
????????????1.客户端
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; ? /* * 需求:客户端键盘录入,服务器输出文本文件 */ public?class ClientDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("192.168.12.92", 23456); ? ????????// 封装键盘录入 ????????BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); ????????// 封装通道内的数据 ????????BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( ????????????????s.getOutputStream())); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????if ("over".equals(line)) { ????????????????break; ????????????} ? ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ? ????????// bw.close(); ????????// br.close(); ????????s.close(); ????} } |
?
?
????????????2.服务器端:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class ServerDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(23456); ? ????????// 监听客户端连接 ????????Socket s = ss.accept(); ? ????????// 封装通道内的数据 ????????BufferedReader br = new BufferedReader(new InputStreamReader( ????????????????s.getInputStream())); ????????// 封装文本文件 ????????BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt")); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ? ????????bw.close(); ????????// br.close(); ????????s.close(); ????????// ss.close(); ????} } |
?
????????????e:客户端读取文本文件服务器控制台输出
????????????1.客户端
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.Socket; ? /* * 需求:客户端读取文本文件,服务器输出到控制台 */ public?class ClientDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建Socket对象 ????????Socket s = new Socket("192.168.12.92", 34567); ? ????????// 封装文本文件 ????????BufferedReader br = new BufferedReader(new FileReader( ????????????????"InetAddressDemo.java")); ????????// 封装通道内的流 ????????BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( ????????????????s.getOutputStream())); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ? ????????br.close(); ????????s.close(); ????} } |
?
?
????????????2.服务器端:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class ServerDemo { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(34567); ? ????????// 监听客户端连接 ????????Socket s = ss.accept(); ? ????????// 封装通道内的流 ????????BufferedReader br = new BufferedReader(new InputStreamReader( ????????????????s.getInputStream())); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { ????????????System.out.println(line); ????????} ? ????????//关闭连接 ????????s.close(); ????} } |
?
????????????f:客户端读取文本文件服务器写到文本文件
????????????1.客户端
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; ? /* * 需求:上传一个文件到服务器 * * 按照我们正常的思路加入反馈信息,结果却没反应。为什么呢? * 读取文本文件是可以以null作为结束信息的,但是呢,通道内是不能这样结束信息的。 * 所以,服务器根本就不知道你结束了。而你还想服务器给你反馈。所以,就相互等待了。 * * 如何解决呢? * A:在多写一条数据,告诉服务器,读取到这条数据说明我就结束,你也结束吧。 * ????????这样做可以解决问题,但是不好。 * B:Socket对象提供了一种解决方案 * ????????public void shutdownOutput() */ ? public?class UploadClient { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("192.168.12.92", 11111); ? ????????// 封装文本文件 ????????BufferedReader br = new BufferedReader(new FileReader( ????????????????"InetAddressDemo.java")); ????????// 封装通道内流 ????????BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( ????????????????s.getOutputStream())); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { // 阻塞 ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ???????? ????????//自定义一个结束标记 //????????bw.write("over"); //????????bw.newLine(); //????????bw.flush(); ???????? ????????//Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了 ????????s.shutdownOutput(); ? ????????// 接收反馈 ????????BufferedReader brClient = new BufferedReader(new InputStreamReader( ????????????????s.getInputStream())); ????????String client = brClient.readLine(); // 阻塞 ????????System.out.println(client); ? ????????// 释放资源 ????????br.close(); ????????s.close(); ????} } |
?
?
????????????2.服务器端:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class UploadServer { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器端的Socket对象 ????????ServerSocket ss = new ServerSocket(11111); ? ????????// 监听客户端连接 ????????Socket s = ss.accept();// 阻塞 ? ????????// 封装通道内的流 ????????BufferedReader br = new BufferedReader(new InputStreamReader( ????????????????s.getInputStream())); ????????// 封装文本文件 ????????BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { // 阻塞 ????????// if("over".equals(line)){ ????????// break; ????????// } ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ? ????????// 给出反馈 ????????BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter( ????????????????s.getOutputStream())); ????????bwServer.write("文件上传成功"); ????????bwServer.newLine(); ????????bwServer.flush(); ? ????????// 释放资源 ????????bw.close(); ????????s.close(); ????} } |
?
????????????g:上传图片
????????????1.发送端
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; /* * 需求:上传图片 */ public?class UploadClient { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("192.168.12.92", 19191); ? ????????// 封装图片文件 ????????BufferedInputStream bis = new BufferedInputStream(new FileInputStream( ????????????????"林青霞.jpg")); ????????// 封装通道内的流 ????????BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); ? ????????byte[] bys = new?byte[1024]; ????????int?len = 0; ????????while ((len = bis.read(bys)) != -1) { ????????????bos.write(bys, 0, len); ????????????bos.flush(); ????????} ???????? ????????s.shutdownOutput(); ? ????????// 读取反馈 ????????InputStream is = s.getInputStream(); ????????byte[] bys2 = new?byte[1024]; ????????int?len2 = is.read(bys2); ????????String client = new String(bys2, 0, len2); ????????System.out.println(client); ? ????????// 释放资源 ????????bis.close(); ????????s.close(); ????} } |
?
?
????????????2.服务器端:
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class UploadServer { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(19191); ? ????????// 监听客户端连接 ????????Socket s = ss.accept(); ? ????????// 封装通道内流 ????????BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); ????????// 封装图片文件 ????????BufferedOutputStream bos = new BufferedOutputStream( ????????????????new FileOutputStream("mn.jpg")); ? ????????byte[] bys = new?byte[1024]; ????????int?len = 0; ????????//读取文件 ????????while ((len = bis.read(bys)) != -1) { ????????????bos.write(bys, 0, len); ????????????bos.flush(); ????????} ? ????????// 给客户端一个反馈 ????????OutputStream os = s.getOutputStream(); ????????os.write("图片上传成功".getBytes()); ? ????????bos.close(); ????????s.close(); ????} } |
?
????????????h:多线程改进上传文件
????????????1.多线程类
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; /* * 多线程类: */ public?class UserThread implements Runnable { ????private Socket s; ? ????public UserThread(Socket s) { ????????this.s = s; ????} ? ????@Override ????public?void run() { ????????try { ????????????// 封装通道内的流 ????????????BufferedReader br = new BufferedReader(new InputStreamReader( ????????????????????s.getInputStream())); ????????????// 封装文本文件 ????????????// BufferedWriter bw = new BufferedWriter(new ????????????// FileWriter("Copy.java")); ? ????????????// 为了防止文件名称冲突 ????????????String newName = System.currentTimeMillis() + ".java"; ????????????BufferedWriter bw = new BufferedWriter(new FileWriter(newName)); ? ????????????String line = null; ????????????while ((line = br.readLine()) != null) { // 阻塞 ????????????????bw.write(line); ????????????????bw.newLine(); ????????????????bw.flush(); ????????????} ? ????????????// 给出反馈 ????????????BufferedWriter bwServer = new BufferedWriter( ????????????????????new OutputStreamWriter(s.getOutputStream())); ????????????bwServer.write("文件上传成功"); ????????????bwServer.newLine(); ????????????bwServer.flush(); ? ????????????// 释放资源 ????????????bw.close(); ????????????s.close(); ????????} catch (IOException e) { ????????????e.printStackTrace(); ????????} ????} ? } |
?
????????????2.客户端
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; /* * 需求:多线程上传文件 */ public?class UploadClient { ????public?static?void main(String[] args) throws IOException { ????????// 创建客户端Socket对象 ????????Socket s = new Socket("192.168.12.92", 11111); ? ????????// 封装文本文件 ????????// BufferedReader br = new BufferedReader(new FileReader( ????????// "InetAddressDemo.java")); ????????BufferedReader br = new BufferedReader(new FileReader( ????????????????"ReceiveDemo.java")); ????????// 封装通道内流 ????????BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( ????????????????s.getOutputStream())); ? ????????String line = null; ????????while ((line = br.readLine()) != null) { // 阻塞 ????????????bw.write(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ? ????????// Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了 ????????s.shutdownOutput(); ? ????????// 接收反馈 ????????BufferedReader brClient = new BufferedReader(new InputStreamReader( ????????????????s.getInputStream())); ????????String client = brClient.readLine(); // 阻塞 ????????System.out.println(client); ? ????????// 释放资源 ????????br.close(); ????????s.close(); ????} } |
?
?
????????????3.服务器端:
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /* * 服务器端: */ public?class UploadServer { ????public?static?void main(String[] args) throws IOException { ????????// 创建服务器Socket对象 ????????ServerSocket ss = new ServerSocket(11111); ????????//循环接收客户端的连接 ????????while (true) { ????????????Socket s = ss.accept(); ????????????new Thread(new UserThread(s)).start(); ????????} ????} } |
?
?