十三.Java基础_网络编程
来源:互联网 发布:js获取input上传文件 编辑:程序博客网 时间:2024/04/29 01:34
Java基础_网络编程
一.UDP和TCP传输各自的特点
UDP的特点:将数据及源和目的封装在大小限制在64K内的数据包中,不需要建立连接,速度快,也因此是不可靠协议。
TCP的特点:需要建立连接形成传输数据的同道,在连接中进行大数据量传输,因为必须建立连接,导致效率会稍低,但通过三次握手完成连接,是可靠协议。
二.Socket
网络编程其实就是Socket编程:
Socket就是为网络服务提供的一种机制,网络通信其实就是Socket间的通信,通信的两端都有Socket,数据在两个Socket间通过IO传输,毕老师形象的将其比喻为码头,要先建立两地的码头才能进行互相输送数据,编程时要先建立Socket服务。
三.IP地址及端口
IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的。IP地址是网络中设备的标识,本地IP地址为:127.0.0.1,主机名为:localHost。
端口用于标识进程的逻辑地址,就是不同进程的标识,有效端口:0~65535,其中0~1024为系统使用或保留端口。
一些重要的方法:
InetAddress.getLocalHost();返回本地主机
InetAddress.getByName(String host):通过主机名字获取主机的IP地址
InetAddress.getHostAddress(); 返回IP地址字符串
InetAddress.getHostName().返回此IP地址的主机名
四.应用实例
UDP协议传输:
(1)要求:用UDP协议从一台主机发送一串数据”Hello java!”到另外一台主机
思路:
发送端:1.建立UDP Socket服务
2.提供数据并封装到数据包中
3.通过Socket服务发送数据
4.关闭资源
接收端:1.建立UDP Socket服务
2.建立用于接收数据的数据包,用数据包接收数据是因为数据包中有更 多的处理接收到的数据的功能;
3.通过Socket 服务的receive功能将接收的数据存入数据包中
4.关闭资源
下面是代码:
import java.net.*; class UDPsend { public static void main(String[] args) throws Exception { //建立UDP Socket服务 DatagramSocket ds = new DatagramSocket(12345); byte[] buf = "Hello java!".getBytes(); //建立数据包封装发送的数据,new DategramPacket(byte[] buf,int length,InetAddress address,int port); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("aisl-PC"),10000); //通过Socket的功能发送数据 ds.send(dp); //关闭资源 ds.close(); } } class UDPreceive { public static void main(String[] args) throws Exception { DatagramSocket ds = new DatagramSocket(10000); byte[] buf = new byte[1024]; //建立数据包用来接收数据 DatagramPacket dp = new DatagramPacket(buf,buf.length); //通过Socket的功能接收数据 ds.receive(dp); //利用数据包的功能获取数据的一些信息 String ip = dp.getAddress().getHostAddress(); int port = dp.getPort(); String data = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+"--"+data+"--"+port); ds.close(); } }
(2)要求:用UDP协议实现两台主机类似QQ的DOS版聊天,
思路:1.要让两台主机的软件上都有接收和发送功能,那么就要让这个程序同 时具有接收和发送功能;
2.要实现同时具有接收和发送功能就要考虑用多线程。
import java.io.*; import java.net.*; class UDPliaotian { public static void main(String[] args) throws Exception { //先定义发送端和接收端Socket服务 DatagramSocket ds = new DatagramSocket(); DatagramSocket ds1 = new DatagramSocket(10001); //开启线程 new Thread(new send(ds)).start(); new Thread(new receive(ds1)).start(); } } //发送端 class send implements Runnable { private DatagramSocket ds; //构造函数接收一个DatatramSocket send(DatagramSocket ds) { this.ds=ds; } //覆盖父类中的run方法 public void run() { try { //定义一个IO读取流读取键盘录入 BufferedReader bfr = new BufferedReader( new InputStreamReader(System.in)); String line = null; while ((line = bfr.readLine())!=null) { if ("88".equals(line)) break; byte[] buf = line.getBytes(); //建立数据包封装发送的数据,new DategramPacket(byte[] buf,int length,InetAddress address,int port); DatagramPacket dp = new DatagramPacket( buf,buf.length,InetAddress.getByName("127.0.0.255"),10001); //发送数据 ds.send(dp); } } catch (Exception e) { throw new RuntimeException("发送端失败"); } } } //接收端 class receive implements Runnable { private DatagramSocket ds; //构造函数接收一个DatagramSocket receive(DatagramSocket ds) { this.ds=ds; } //覆盖父类中的run方法 public void run() { try { //不断的接收数据 while (true) { byte[] buf = new byte[1024]; //建立数据包用来接收数据 DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp); String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+"::"+data); } } catch (Exception e) { throw new RuntimeException("接收端失败"); } } }
TCP协议传输
(1)要求:让客户端连接服务端,并向服务端发送一段文字,服务端在接收到客 户端发送的文字后向客户端返回一段文字。
思路:
客户端:1.创建Socket服务,并指定要连接的主机和端口
2.获取Socket流中的输出流,将数据写到该流中,通过网络发送给服务端;
3.获取Socket流中的输入流,将服务端反馈的数据获取到,并打印
4.关闭客户端资源
服务端:1.创建ServerSocket服务,获取客户端Socket
2.获取Socket读取流读取客户端发送的数据并打印
3.获取Socket输出流像客户端返回一句话给客户端
4.关闭资源
import java.io.*; import java.net.*; class tcpclient { public static void main(String[] args) throws Exception { //创建Socket服务,并指定要连接的主机和端口 Socket s = new Socket("127.0.0.1",10003); //定义Socket输出流,发送一句话到服务端 OutputStream out = s.getOutputStream(); out.write("服务端你好!我是客户端!".getBytes()); /* InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String (buf,0,len)); */ //获取Socket流中的输入流,将服务端反馈的数据获取到,并打印(也可用注释部分代码实现) BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); String str = bfrin.readLine(); System.out.println(str); s.close(); } } class tcpserve { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10003); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...connection"); //获取Socket读取流读取客户端发送的数据 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); //OutputStream out = s.getOutputStream(); //获取Socket输出流像客户端返回一句话给客户端,(也可用注释部分代码实现) PrintWriter out = new PrintWriter(s.getOutputStream(),true); Thread.sleep(2000); //out.write("收到,我是服务端".getBytes()); out.println("收到,我是服务端"); s.close(); ss.close(); }}
(2)要求:建立一个文本转换服务器
客户端给服务端发送文本,服务端会将文本转换成大写再返回给客户端
而且客户端可以不断的进行文本转换,当客户端输入over时,转换结束
思路:
客户端:1.建立Socket服务
2.定义IO读取流获取键盘录入
3.定义Socket输出流将键盘录入的数据发送给服务端
4.定义Socket读取流获取服务端返回大写数据并打印
5.关闭资源
服务端:1.确定源为Socket读取流,目的为Socket输出流
2.建立ServerSocket服务,接收客户端Socket
3.定义Socket读取流获取客户端发送来的数据
4.定义Socket输出流将处理后的数据发送回客户端
5.关闭资源
import java.io.*; import java.net.*; class tcpclient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10005); //定义读取流读取键盘录入 BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); //定义Socket输出流, BufferedWriter bfwout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); //定义Socket读取流读取服务端返回的数据 BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while ((line = bfr.readLine())!=null) { if ("over".equals(line)) break; bfwout.write(line); bfwout.newLine(); bfwout.flush(); String str = bfrin.readLine(); System.out.println("server:"+str); } bfr.close(); s.close(); } } /* 服务端: 源:socket读取流 目的:socket输出流 都是文本,可装饰 */ class tcpserve { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10005); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"....已连接"); //定义Socket读取流用来获取客户端发送来的数据 BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); //定义Socket输出流用来将处理后的数据发送回客户端 BufferedWriter bfwout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); String line = null; while ((line = bfrin.readLine())!=null) { //转换成大写并发送 bfwout.write(line.toUpperCase()); bfwout.newLine(); bfwout.flush(); } s.close(); ss.close(); }}
(3)要求:客户端向服务端上传文件
客户端向服务端发送一个文件,服务端接收文件并保存。
这里是上传一个文本文件,如果不是纯文本文件,那么程序里要使用字节流读写
import java.io.*; import java.net.*; class tcpclient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10006); BufferedReader bfr = new BufferedReader(new FileReader("Demo.java")); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while ((line=bfr.readLine())!=null) { out.println(line); } s.shutdownOutput();//关闭客户端输出流,相当于给流中加入一个结束标记-1 BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); String str = bfrin.readLine(); System.out.println(str); bfr.close(); s.close(); } } class tcpserver { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...连接成功"); BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter pw = new PrintWriter(new FileWriter("server.txt"),true); String line = null; while ((line=bfrin.readLine())!=null) { pw.println(line); } PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("上传成功"); pw.close(); s.close(); ss.close(); } }
注意:这里面有一个重要的方法,shutdownOutput():禁用此套接字的输出流,也就是关闭客户端输出流,相当于给流中加入一个结束标记,如果程序中没有实现这个步骤,那么程序运行结果为:客户端在将文件上传完成后,服务端和客户端都为无限等待状态,程序不结束。
(4)要求:客户端向服务端上传一个图片
程序中要用字节流进行文件的读写
import java.io.*; import java.net.*; class tcpclient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10007); FileInputStream fis = new FileInputStream("1.jpg"); OutputStream out = s.getOutputStream(); int len = 0; byte[] buf = new byte[1024]; while ((len=fis.read(buf))!=-1) { out.write(buf,0,len); } s.shutdownOutput(); BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); String str = bfrin.readLine(); System.out.println(str); fis.close(); s.close(); } } class tcpserver { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10007); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...连接成功"); InputStream in = s.getInputStream(); FileOutputStream fos = new FileOutputStream("server.jpg"); int len = 0; byte[] buf = new byte[1024]; while ((len=in.read(buf))!=-1) { fos.write(buf,0,len); } PrintWriter pw = new PrintWriter(s.getOutputStream(),true); pw.println("上传成功"); fos.close(); s.close(); ss.close(); }}
(5)练习
需求:
1.客户端登陆服务器,登陆三次错误,退出程序
2.允许多用户同时登陆
思路:
客户端:
1.建立Socket服务并指定要连接的主机地址以及程序端口
2.定义IO读取流读取键盘录入数据
3.获取Socket输出流发送数据
4.获取Socket读取流读取服务端返回的数据
5.关闭资源
服务端:
1.要模拟登陆功能需要一个数据库,可以用记事本做一个极简数据库
2.建立ServerSocket服务,并指定一个监听接口
3.获取Socket读取流读取客户端发送的数据
3.建立文件读取流读取数据库中的数据与客户端发送的数据进行比较
4.获取Socket输出流向客户端返回信息
5.关闭资源
代码演示:
import java.io.*; import java.net.*; class TCPclient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10008); //定义IO读取流读取键盘录入的数据 BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); //获取Socket输出流发送数据 PrintWriter pw = new PrintWriter(s.getOutputStream(),true); //获取Socket读取流读取服务端返回的数据 BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream())); for (int x=1;x<=3;x++ ) { String line = bfr.readLine(); if (line==null) break; pw.println(line); String str = bfrin.readLine(); System.out.println("info:"+str); if (str.contains("欢迎")) break; } bfr.close(); s.close(); } } class TCPserver { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10008); while (true) { Socket s = ss.accept(); new Thread(new ServerThread(s)).start(); } } } class ServerThread implements Runnable { private Socket s; ServerThread(Socket s) { this.s = s; } public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"....connected"); try { for (int x=1;x<=3 ;x++ ) { //Socket流接收客户端发送的数据 BufferedReader bfrin = new BufferedReader( new InputStreamReader(s.getInputStream())); //定义IO读取流查找建立的极简数据库 BufferedReader bfr = new BufferedReader(new FileReader("user.txt")); PrintWriter pw = new PrintWriter(s.getOutputStream(),true); String str = bfrin.readLine(); if(str==null) break; String name=null; Boolean flag = false; while ((name=bfr.readLine())!=null) { if (name.equals(str)) { flag = true; break; } } if (flag) { System.out.println(ip+"...已登陆"); pw.println("登陆成功,欢迎进入"); break; } else { System.out.println(ip+"...尝试登陆"); pw.println(str+"用户名不存在"); } } s.close(); } catch (Exception e) { throw new RuntimeException("效验失败"); } } }
(6)练习:一个极简仿QQ聊天界面代码示例
服务端:
import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; //服务端 class Demo { public static void main(String[] args) throws Exception { liaotian lt = new liaotian(); } } class liaotian { //建立服务端Socket服务,并设定服务端端口 ServerSocket ss = new ServerSocket(12345); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); //定义Socket读取流读取客户端发送来的数据 private InputStream in = s.getInputStream(); //定义Socket输出流用来发送数据给客户端 private OutputStream out = s.getOutputStream(); liaotian() throws Exception { init(); } private Frame f; private Button b; //定义两个文本区域,类似QQ聊天界面的读取区域和输入区域 private TextArea tax,tad; public void init() throws Exception { //对软件窗体进行基本设置 f = new Frame("my window fuwuduan"); f.setBounds(300,100,500,600); f.setLayout(new FlowLayout()); tax = new TextArea(8,63); tad = new TextArea(20,63); b = new Button("发送"); f.add(tad); f.add(tax); f.add(b); myEvent(); //显示窗体 f.setVisible(true); //使窗体大小不能被改变 f.setResizable(false); tad.append(ip+"连接成功\r\n"); out.write("连接成功".getBytes()); while (true)//不断的接收数据 { byte[] buf = new byte[1024]; int len = in.read(buf); String strr = new String(buf,0,len); tad.append("客户端IP-"+ip+":"+strr+"\r\n"); } } private void send() throws Exception//发送数据 { String str = tax.getText()+" "; tad.append("我:"+str+"\r\n"); tax.setText(""); out.write(str.getBytes()); } private void myEvent() throws Exception { f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { send(); } catch (Exception e1) { throw new RuntimeException("asdfas"); } } }); } }
客户端:
import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; //客户端 class Demo { public static void main(String[] args) throws Exception { liaotian lt = new liaotian(); } } class liaotian { //这里改成服务器主机的IP地址,“12345”为服务器端口 Socket s = new Socket("127.0.0.1",12345); //定义Socket读取流读取服务端发送来的数据 private InputStream in = s.getInputStream(); //定义Socket输出流用来发送数据给服务端 private OutputStream out = s.getOutputStream(); liaotian() throws Exception { init(); } private Frame f; private Button b; //定义两个文本区域,类似QQ聊天界面的读取区域和输入区域 private TextArea tax,tad; public void init() throws Exception { //对软件窗体进行基本设置 f = new Frame("my window kehuduan"); f.setBounds(300,100,500,600); f.setLayout(new FlowLayout()); tax = new TextArea(8,63); tad = new TextArea(20,63); b = new Button("发送"); f.add(tad); f.add(tax); f.add(b); //加载窗体上的事件 myEvent(); //使窗体大小不能被改变 f.setResizable(false); //显示窗体 f.setVisible(true); while (true)//不断的接收数据 { byte[] buf = new byte[1024]; int len = in.read(buf); String strr = new String(buf,0,len); tad.append("主机:"+strr+"\r\n"); } } private void send() throws Exception//发送数据 { String str = tax.getText()+" "; tad.append("我:"+str+"\r\n"); //在发送之前将输入区域里面的数据清空 tax.setText(""); out.write(str.getBytes()); } private void myEvent() throws Exception { f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); //点击"发送"按钮发送数据 b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { send(); } catch (Exception e1) { throw new RuntimeException("发送失败"); } } }); }}
(7)自定义服务端
需求:自定义一个服务端向客户短发送一条数据,用IE浏览器作为客户端连接服务端 接收数据
代码如下:
import java.io.*; import java.net.*; class tcpserver { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(11000); Socket s = ss.accept(); System.out.println(s.getInetAddress().getHostAddress()); //获取Socket输出流发送数据 PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("<font size='3' color='red'>客户端你好!</font>"); s.close(); ss.close(); } }
- 十三.Java基础_网络编程
- Java基础(十三)——网络编程
- Java基础(十三)——网络编程
- Java基础_网络编程
- java基础_网络编程
- java基础_网络编程
- Java笔记二十三.网络编程基础与UDP编程
- Java基础<十四>_网络编程
- java基础26_网络编程
- java基础16_网络编程
- java基础整理二十三(网络编程)
- JAVA(十三)网络通信编程
- 网络编程_网络编程基础
- 网络编程_进程基础
- 黑马程序员——Java基础_网络编程
- 黑马程序员—java基础_网络编程
- java知识总结(十三)网络编程
- Java基础知识_网络编程
- 十五.Java基础加强(一)
- 选举计数
- 【路径相关方法】4,计算文件夹大小
- 3大背包问题的个人解释
- [过年菜谱之]红烧甲鱼
- 十三.Java基础_网络编程
- 简单的多线程实例
- CodeForces 385D Bear and Floodlight
- Gas Station
- 大数据处理书籍
- [过年菜谱之]杭椒牛柳
- JAVA 数据类型转换
- C# 网络编程之基于SMTP发送电子邮件
- Django的安装