网络编程——第一部分
新博客地址:Temi
第一讲,第二讲:Java基础第23天-01-网络编程(概述),第23天-02-网络编程(概述2)
一,网络通信步骤:
- 找到对方(通过IP)。
- 数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。====端口(逻辑端口)====
- 定义通信规则,这个规则成为协议。国际标准化组织定义了TCP/IP协议。======有效端口:0 ~65535,系统使用或保留的端口是:0~ 1024。======
第三讲:(网络模型)
一,各个层次的协议 (通常用户操作的是应用层,而编程人员需要做的是传输层和网际层):
- 网际层:IP协议。
- 传输层:TCP/UDP协议。
- 应用层:HTTP/FTP 协议。(web开发)。
二,网络通讯要素:
- IP地址:
- 网络中设备的标识。
- 不易记忆,可用主机名。
- 本地回环地址。127.0.0.1 。主机名:localhost
- 端口号:
- 用于表示进程的逻辑地址。不同进程的标识。
- 有效端口:0-65535,其中1-1024系统使用或保留端口。
三,涉及到的类:
- public class InetAddress extends Object implements Serializable 此类表示互联网协议 (IP) 地址。 ====注:此类没有构造方法=====
- 方法:public static InetAddress getByName (String host) throws UnknownHostException 在给定主机名的情况下确定主机的 IP 地址。
- 方法:public static InetAddress[] getAllByName(String host) throws UnknownHostException 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
- 方法:public static InetAddress getByAddress(byte[] addr) throws UnknownHostException 在给定原始 IP 地址的情况下,返回
InetAddress
对象。 - 方法:public String getHostName() 获取此 IP 地址的主机名。
- 方法:public String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。
四,代码练习:
1 import java.net.*; 2 3 public class IPDemo { 4 public static void main(String[] args) throws UnknownHostException { 5 //声明地址类,表示本地主机 6 InetAddress i = InetAddress.getLocalHost(); 7 8 //输出本地主机的IP地址 9 System.out.println(i.getHostAddress()); 10 11 //已主机名的方式找到主机 12 InetAddress my = InetAddress.getByName("Lenovo-PC"); 13 14 //输出主机地址 15 System.out.println(my.getHostAddress()); 16 17 18 //获取百度所有主机 19 InetAddress[] ia = InetAddress.getAllByName("www.baidu.com"); 20 21 //输出百度主机地址 22 for(InetAddress inet : ia){ 23 24 System.out.println(inet.getHostName()+"::"+inet.getHostAddress()); 25 } 26 27 } 28 }
第四讲:网络编程(IP地址)
第五讲:网络编程(TCP和UDP)
一,TCP 和 UDP 简介:
- UDP(面向无连接,明确了对方的端口,无论在不在网上,只管传输,不在就会丢失数据。只求速度,应用于网络视频会议和聊天等应用程序中。)
- 将数据及源和目的封装在数据包中,不需要建立连接。
- 每个数据包的大小限制在64k内。
- 因为无连接,是不可靠协议。
- 不需要建立连接,所以速度快。
- TCP( 是面向连接的,必须连接成功才能传输数据,应用于下载等程序上)
- 建立连接形成传输数据的通道。
- 可在连接中进行大数据量传输。
- 通过三次握手完成数据连接,是可靠协议。===注:三次握手:第一次本方发送请求,第二次对方确认连接,第三次本方再次确认连接成功。====
- 必须建立连接,效率稍低。
第六讲,第七讲:网络编程(Socket),网络编程(Udp-发送端)
一,Socket 简介:
- Socket 是为网络服务提供的一种机制。
- 通信的两段都有Socket。
- 网络通信其实就是Socket之间的通信。
- 数据在两个Socket之间通过IO传输。
二,DatagramSocket 类简介:
- public class DatagramSocketextends Object 此类表示用来发送和接收数据报包的套接字。 ===注:在 DatagramSocket 上总是启用 UDP 广播发送。====
- 构造方法:public DatagramSocket() throws SocketException 构造数据报套接字并将其绑定到本地主机上任何可用的端口。
- 构造方法:public DatagramSocket(int port) throws SocketException 创建数据报套接字并将其绑定到本地主机上的指定端口。
- 方法:public InetAddress getInetAddress() 返回此套接字连接的地址。如果套接字未连接,则返回 null。
- 方法:public int getPort() 返回此套接字的端口。如果套接字未连接,则返回 -1。
- public void send (DatagramPacket p) throws IOException 从此套接字发送数据报包。
三,DatagramPacket 类简介(DatagramPacket
包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。):
- public final class DatagramPacketextends Object 此类表示数据报包。
- 构造方法:public DatagramPacket(byte[] buf, int offset, int length, InetAddress address,int port) 构造数据报包,用来将长度为
length
偏移量为offset
的包发送到指定主机上的指定端口号。 - 方法:public InetAddress getAddress() 返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
- 方法:public int getPort() 返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
- 方法:public byte[] getData() 返回数据缓冲区。接收到的或将要发送的数据从缓冲区中的偏移量
offset
处开始,持续length
长度。 - 方法:public int getOffset() 返回将要发送或接收到的数据的偏移量。
- 方法:public int getLength() 返回将要发送或接收到的数据的长度。
四,代码练习:
1 import java.net.*; 2 3 public class UdpSend { 4 public static void main(String[] args) throws Exception { 5 6 //创建Udp服务 7 DatagramSocket ds = new DatagramSocket(); 8 9 //获得发送数据 10 byte[] b = "这是发送信息".getBytes(); 11 12 //构造数据包 13 DatagramPacket dp = new DatagramPacket(b, b.length,InetAddress.getByName("localhost"),8080); 14 15 //发送数据 16 ds.send(dp); 17 18 //关闭资源 19 ds.close(); 20 } 21 }
第八讲:网络编程(Udp-接收端)
一,Udp 的 Socket 服务建立步骤。
- 建立DatagramSocket和DatagramPacket对象。
- 建立发送端(建立UDPSocket服务,在此无需指定端口,也可以将端口加入。如果不指定的话,系统会随机分配一个端口,如第一次运行时端口为1093,那么第二次就会顺延为1094,再运行会一直顺延,因为之前的端口还没有得到释放,所以会顺延端口号值。),接受端(定义UDPSocket服务。通常会监听一个端口,其实就是给这个接收网路应用程序定义数字标识,方便于明确哪些数据过来该应用程序可以处理。)。
- 建立数据包。
- 调用Socket发送接收方法。
- 关闭Socket。
二,代码练习:
1 import java.net.DatagramPacket; 2 import java.net.DatagramSocket; 3 4 public class UdpRece { 5 public static void main(String[] args) throws Exception{ 6 7 //定义接受端套接字 8 DatagramSocket ds = new DatagramSocket(10000); 9 10 //定义字节数组,保存接受内瓤 11 byte buf[] = new byte[1024]; 12 13 //定义数据包,接受数据 14 DatagramPacket dp = new DatagramPacket(buf,buf.length); 15 16 //接受数据 17 ds.receive(dp); 18 19 //将字节构造成字符 20 String revece = new String(buf); 21 22 //标记发送端的端口 23 int port = dp.getPort(); 24 25 //标记发送端的地址 26 String address =dp.getAddress().getHostAddress(); 27 28 //输出内容 29 System.out.println("address:"+address+"port"+port+"revece"+revece); 30 31 } 32 }
第九讲:网络编程(UDP-键盘录入方式数据)
一,一个特殊的IP地址: 192.168.1.255 广播地址。
二代码练习:
1 import java.net.*; 2 import java.io.*; 3 4 5 public class UpdSend2 { 6 public static void main(String[] args) throws Exception { 7 8 //创建套接字对象 9 DatagramSocket ds = new DatagramSocket(); 10 11 //创建数组接收对象 12 byte b[] = new byte[1024]; 13 14 //接受键盘输入 15 System.in.read(b); 16 17 //构建数据包 18 DatagramPacket dp = new DatagramPacket(b,b.length,InetAddress.getByName("127.0.0.1"),10001); 19 20 //发送数据包 21 ds.send(dp); 22 23 //关闭资源 24 ds.close(); 25 } 26 }
第十讲:网络编程(UDP-聊天)
一,需求分析:
- 编写一个聊天程序 有收数据的部分,和发数据的部分 这两部分需要同时执行 那就需要用到多线程技术 一个线程控制收,一个线程控制发
二,思路分析:
- 接收端和发送端需要同时完成收发功能。
- 接受数据,发送数据应当封装到两个线程中。
三,代码练习:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建线程类,此类启动一个线程,执行在端口10001接受网络数据操作 6 class MyRece implements Runnable{ 7 8 //覆盖run()方法 9 @Override 10 public void run(){ 11 12 //循环接受数据 13 while (true){ 14 try { 15 16 //创建套接字对象,在端口10001接受网络数据 17 DatagramSocket ds = new DatagramSocket(10001); 18 19 //存储接受内容 20 byte b[] = new byte[1024]; 21 22 //创建数据包对象 23 DatagramPacket dp = new DatagramPacket(b,b.length); 24 25 //接受数据 26 ds.receive(dp); 27 28 //打印接受到的数据 29 System.out.println("主机:"+dp.getAddress()+"发来:"+new String(dp.getData(),0,dp.getLength())); 30 31 //判断是否关闭程序 32 if(dp.getData().toString().trim().equals("886")) 33 //当对放发送886程序结束 34 break; 35 } catch (SocketException e) { 36 System.out.println("网络错误"+e.toString()); 37 }catch (IOException e){ 38 System.out.println("IO错误"+e.toString()); 39 } 40 41 } 42 } 43 } 44 45 46 //创建一个类启动一个线程,该线程实现发送用户从键盘输入的内容 47 class MySend implements Runnable{ 48 49 //覆盖方法 50 @Override 51 public void run(){ 52 //循环接受发送 53 while(true){ 54 55 try{ 56 //创建套接字对象 57 DatagramSocket ds = new DatagramSocket(); 58 59 //创建缓冲输入流,从键盘接受数据 60 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 61 62 //存储键盘输入的一行数据 63 String line = null; 64 65 //如果用户输入886 ,发送数据,并结束程序运行 66 if((line=br.readLine()).trim().equals("886")){ 67 DatagramPacket dp = new DatagramPacket(line.getBytes(),line.getBytes().length,InetAddress.getByName("127.0.0.1"),10001); 68 69 ds.send(dp); 70 break; 71 } 72 73 //发送数据 74 DatagramPacket dp = new DatagramPacket(line.getBytes(),line.getBytes().length,InetAddress.getByName("127.0.0.1"),10001); 75 76 ds.send(dp); 77 78 }catch(IOException e){ 79 System.out.println("IO异常"+e.toString()); 80 } 81 82 } 83 } 84 } 85 public class ChatDemo { 86 public static void main(String[] args) { 87 88 89 //创建线程对象 90 Thread t1 = new Thread(new MyRece()); 91 Thread t2 = new Thread(new MySend()); 92 93 //启动线程 94 t1.start(); 95 t2.start(); 96 } 97 }
第十一讲:网络编程(TCP传输)
一,TCP传输过程。
- 建立,Socket(客户端) 和ServerSocket(服务端,服务端需要明确它要处理的数据是从哪个端口进入的。)。=====因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,再通过该通道进行数据的传输。===
- 通过Socket中的IO流进行数据的传输。
- 关闭Socket。
- 客户端和服务器端是两个独立的应用程序。
二,涉及道的类了解:
- Socket:
- 定义:public class Socket extends Object 此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
- 构造方法:public Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字 ==注:创建空参数的客户端对象,一般用于服务端接收数据==
- 构造方法:public Socket(String host, int port) throws UnknownHostException, IOException 创建一个流套接字并将其连接到指定主机上的指定端口号。
- 方法:public void bind(SocketAddress bindpoint) throws IOException 将套接字绑定到本地地址。如果地址为
null
,则系统将挑选一个临时端口和一个有效本地地址来绑定套接字。 - 方法:public InetAddress getInetAddress() 返回套接字连接的地址。
- 方法:public int getPort() 返回此套接字连接到的远程端口。
- 方法:public InetAddress getLocalAddress() 获取套接字绑定的本地地址。
- 方法:public int getLocalPort() 返回此套接字绑定到的本地端口。
- 方法:public InputStream getInputStream() throws IOException 返回此套接字的输入流。
- 方法:public OutputStream getOutputStream() throws IOException 返回此套接字的输出流。
- ServerSocket:
- 类的定义:public class ServerSocket extends Object 此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
- 构造方法:public ServerSocket() throws IOException 创建非绑定服务器套接字。
- 构造方法:public ServerSocket(int port) throws IOException 创建绑定到特定端口的服务器套接字。
- 方法:public Socket accept() throws IOException 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
- 方法:public void bind(SocketAddress endpoint) throws IOException 将
ServerSocket
绑定到特定地址(IP 地址和端口号)。 - 方法:public InetAddress getInetAddress() 返回此服务器套接字的本地地址。将此套接字绑定到的地址;如果套接字是未绑定的,则返回
null
。 - 方法:public int getLocalPort() 返回此套接字在其上侦听的端口。此套接字侦听的端口号;如果尚未绑定套接字,则返回 -1。
三,思路分析:
客户端:
通过查阅Socket对象的API文档,发现在该对象在建立时,就可去连接指定主机,因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,再通过该通道进行数据的传输。
1)创建Socket服务,并指定要连接的主机端口。通路一建立,就会产生Socket流(包括输入流和输出流),通过方法获取。========注:如果连接失败,会出现异常。连接成功,说明客户端与服务端建立了通道,之后即可以通过IO流交换数据。==========
2)为了发送数据,应获取Socket中的输出流,如果要接收服务端的反馈信息,还需要获取Socket的输入流
3)通过输出流的write()方法将要发送的数据写入到流中
4)关闭Socket流资源
服务端:
服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。需监听一个端口。
1)建立服务端的Socket服务,并监听一个端口。通过ServerSocet带端口参数的构造函数
2)获取连接过来的客户对象,通过ServerSocket的accept()方法,此方法是阻塞式的,如果服务端没有连接到就会一直等待
3)客户端如果发过来数据,则服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过来的数据,并输出到指定目的地。当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
4)关闭服务端(可选)。一般服务端是常开的,因为在实际应用中,随时有客户端在请求连接和服务。但这里需要定时关闭客户端对象流,避免某一个客户端长时间占用服务器端。
四,代码练习:
服务器端:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建TCP服务器端,接受消息 6 public class TCPServ { 7 public static void main(String[] args) { 8 9 try { 10 11 //创建服务器端套接字,在指定端口监听 12 ServerSocket ss = new ServerSocket(20000); 13 14 //获得接收到的套接字的输入流 15 InputStream is = ss.accept().getInputStream(); 16 17 //存储数据 18 byte b[] = new byte[1024]; 19 20 //读入数据 21 is.read(b); 22 s.close(); 23 //打印 24 System.out.println(new String(b,0,b.length)); 25 26 } catch (IOException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 } 31 }
客户端:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建客户端,以TCP方式连接到远程服务器 6 class TCPClient { 7 public static void main(String[] args) { 8 9 10 try { 11 12 //创建客户端套接字,连接到制定主机的20000端口上 13 Socket s = new Socket(InetAddress.getByName("202.206.154.123"), 20000); 14 15 //获得到远端主机的输出流 16 OutputStream out = s.getOutputStream(); 17 18 //输出数据 19 out.write("您好".getBytes()); 20 //关闭资源 21 s.close(); 22 } catch (UnknownHostException e) { 23 System.out.println("为找到主机"+e.toString()); 24 } catch (IOException e) { 25 System.out.println("IO异常"+e.toString()); 26 } 27 } 28 }
第十二讲:网络编程(TCP传输2)
一,练习:需求分析:客户端给服务端发送数据,服务端收到后,给客户端反馈信息
二,代码练习:
客户端:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建客户端,以TCP方式连接到远程服务器 6 class TCPClient { 7 public static void main(String[] args) { 8 9 10 try { 11 12 //创建客户端套接字,连接到制定主机的20000端口上 13 Socket s = new Socket(InetAddress.getByName("202.206.154.123"), 20000); 14 15 //获得到远端主机的输出流 16 OutputStream out = s.getOutputStream(); 17 18 //输出数据 19 out.write("您好".getBytes()); 20 21 22 //接受服务端消息 23 byte b[] = new byte[1024]; 24 25 //获取输入流 26 InputStream in = s.getInputStream(); 27 28 //标记接受数据量 29 int len=0; 30 31 //读入数据 32 len=in.read(b); 33 34 //输出数据 35 System.out.println(new String(b,0,len)); 36 //关闭资源 37 s.close(); 38 } catch (UnknownHostException e) { 39 System.out.println("为找到主机"+e.toString()); 40 } catch (IOException e) { 41 System.out.println("IO异常"+e.toString()); 42 } 43 } 44 }
服务器端:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建TCP服务器端,接受消息 6 public class TCPServ { 7 public static void main(String[] args) { 8 9 try { 10 11 //创建服务器端套接字,在指定端口监听 12 ServerSocket ss = new ServerSocket(20000); 13 14 Socket s = ss.accept(); 15 //获得接收到的套接字的输入流 16 InputStream is = s.getInputStream(); 17 18 //存储数据 19 byte b[] = new byte[1024]; 20 21 //读入数据 22 is.read(b); 23 24 //打印 25 System.out.println(new String(b,0,b.length)); 26 27 //获取输出流 28 OutputStream out = s.getOutputStream(); 29 30 //向客户端写入数据 31 out.write("客户端你也好".getBytes()); 32 33 //关闭资源 34 s.close(); 35 36 } catch (IOException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 } 41 }
第一十三讲:网络编程(TCP练习)
一,需求分析:
建立一个文本转换服务器, 客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端 ,而且客户端可以不断的进行文本转换。当客户端输入over时,转换结束 。
二,操作步骤:
- 建立服务。
- 获取键盘输入。
- 将数据发给服务端。
- 接受服务端返回的数据。
- 关闭资源。
==============特别注意:如果使用字符缓冲区,写入完毕后,需要加入换行和刷新====================
三,代码练习:
客户端:
1 import java.net.*; 2 import java.io.*; 3 public class TCPClient { 4 public static void main(String[] args) { 5 6 //创建套接字连接服务器 7 Socket s = null; 8 9 //获取输出流 10 OutputStream out = null; 11 12 //获取输入流 13 InputStream is = null; 14 15 16 try { 17 s = new Socket(InetAddress.getByName("127.0.0.1"),10000); 18 19 out = s.getOutputStream(); 20 21 is = s.getInputStream(); 22 } catch (UnknownHostException e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } catch (IOException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } 29 30 31 32 //字符缓冲流增加效率 33 BufferedReader brr = new BufferedReader(new InputStreamReader(is)); 34 35 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out)); 36 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 37 38 try{ 39 //循环发送数据接收数据 40 while(true){ 41 42 //接收读入内容 43 String line = null; 44 45 //读入数据 46 line = br.readLine(); 47 48 //写出数据 49 bw.write(line); 50 51 //换行 52 bw.newLine(); 53 54 //刷新 55 bw.flush(); 56 57 if("over".equals(line)) 58 break; 59 line=brr.readLine(); 60 61 System.out.println(line); 62 } 63 s.close(); 64 }catch (Exception e){ 65 System.out.println(e.toString()); 66 } 67 } 68 }
服务器端:
1 import java.io.*; 2 import java.net.*; 3 4 public class TCPServ { 5 public static void main(String[] args) { 6 7 //创建服务器端套接字,在端口10000监听 8 ServerSocket ss = null; 9 10 //获取与客户端关联的 Socket 11 Socket s = null; 12 13 //获取到客户端的输入流 14 InputStream is = null; 15 16 OutputStream out =null; 17 18 try { 19 ss = new ServerSocket(10000); 20 21 s = ss.accept(); 22 23 out = s.getOutputStream(); 24 is = s.getInputStream(); 25 } catch (IOException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } 29 30 31 32 33 34 //使用字符缓冲流提高效率 35 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 36 37 //字符缓冲流 38 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out)); 39 40 41 try{ 42 //循环接受客户端消息 43 while(true){ 44 45 //接受客户端内容 46 String line = null; 47 48 //读入数据 49 line = br.readLine(); 50 51 //判断是否结束 52 if("over".equals(line)) 53 break; 54 55 //向客户端写入数据 56 bw.write(line.toUpperCase()); 57 58 //换行 59 bw.newLine(); 60 61 //刷新 62 bw.flush(); 63 } 64 ss.close(); 65 }catch(Exception e){ 66 System.out.println(e.toString()); 67 } 68 } 69 }
第一十四讲:网络编程(TCP复制文件)
一,注意的问题:
- 因为客户端将数据发送完毕后,服务端仍然在等待这读取数据,并没有收到结束标记,就会一直等待读取。
- 上个问题解决后,收到的不是指定信息而是null,是因为服务端写入数据后,需要刷新,才能将信息反馈给客服端。
二,解决办法:
- 定义结束标记,先将结束标记发送给服务端,让服务端接收到结束标记,然后再发送上传的数据。但是这样定义可能会发生定义的标记和文件中的数据重复,而导致提前结束。
- 定义时间戳,由于时间是唯一的,在发送数据前,先获取时间,发送完后在结尾处写上相同的时间戳,在服务端,接收数据前先接收一个时间戳,然后在循环中判断时间戳以结束标记。
- 通过socket方法中的shutdownOutput(),关闭输入流资源,从而结束传输流,以给定结束标记。通常用这个方法。
三,代码练习
客户端软件:
1 import java.io.*; 2 import java.net.*; 3 4 public class TextClient { 5 public static void main(String[] args) { 6 7 8 //创建客户端套接字 9 Socket s = null; 10 11 //输出流,输入流对象声明 12 InputStream is = null; 13 14 OutputStream os = null; 15 16 FileInputStream fis = null; 17 18 //标识文件 19 String filename = "E:/sysinfo.txt"; 20 21 File file = new File(filename); 22 23 24 //实例化对象引用 25 try{ 26 s = new Socket(InetAddress.getLocalHost(),10000); 27 28 is = s.getInputStream(); 29 30 os = s.getOutputStream(); 31 32 33 //判断文件是否存在 34 if(!file.exists()) 35 System.out.println("文件不存在"); 36 else { 37 fis = new FileInputStream(file); 38 } 39 }catch(Exception e){ 40 System.out.println(e.toString()); 41 } 42 43 44 //字符缓冲刘提高操作效率 45 BufferedReader br_file = new BufferedReader(new InputStreamReader(fis)); 46 BufferedReader br_net = new BufferedReader(new InputStreamReader(is)); 47 48 //获得服务端输出流 49 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); 50 51 try{ 52 String line = null; 53 54 //循环读取文件并发送到服务器端 55 while ((line=br_file.readLine())!=null){ 56 57 //写入一行字符 58 bw.write(line); 59 60 //写入换行符 61 bw.newLine(); 62 63 //刷新输出流 64 bw.flush(); 65 } 66 67 //写入结束标志 68 bw.write("end"); 69 bw.newLine(); 70 bw.flush(); 71 72 //获取服务端响应 73 line = br_net.readLine(); 74 75 System.out.println(line); 76 }catch(IOException e){ 77 System.out.println(e.toString()); 78 } 79 } 80 }
服务端代码:
1 import java.io.*; 2 import java.net.*; 3 4 public class TextServ { 5 public static void main(String[] args) { 6 7 //创建服务端套接字 8 ServerSocket ss = null; 9 10 //接受客户端 11 Socket s = null; 12 13 ////客户端输入流 14 InputStream is = null; 15 16 //客户端输出流 17 OutputStream os = null; 18 19 //定义文件 20 File file = new File("E:/rever.txt"); 21 22 //定义文件输入流 23 FileOutputStream fos = null; 24 25 //实例化对象 26 try{ 27 ss = new ServerSocket(10000); 28 29 s = ss.accept(); 30 31 is = s.getInputStream(); 32 33 os = s.getOutputStream(); 34 35 fos = new FileOutputStream(file); 36 }catch(Exception e){ 37 System.out.println(e.toString()); 38 } 39 40 //字符缓冲刘提高效率 41 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 42 43 //缓冲输出流。提高效率 44 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); 45 46 47 BufferedWriter bw_file = new BufferedWriter(new OutputStreamWriter(fos)); 48 49 //异常处理 50 try{ 51 52 //接受读入一行字符串 53 String line = null; 54 55 //循环读取 56 while((line=br.readLine())!=null){ 57 //判断是否结束 58 if("end".equals(line)) 59 break; 60 61 //保存到本地文件 62 bw_file.write(line); 63 64 //写入换行符 65 bw_file.newLine(); 66 67 //刷新输出流 68 bw_file.flush(); 69 } 70 71 //给出提示 72 bw.write("写入成功"); 73 74 //写入换行符 75 bw.newLine(); 76 77 //刷新 78 bw.flush(); 79 }catch(Exception e){ 80 System.out.println(e.toString()); 81 } 82 83 } 84 }