黑马程序员—java基础之网络编程

黑马程序员—java基础之网络编程

                                               ------- android培训java培训、期待与您交流! ----------

 

不要试图给自己找任何借口,错误面前没人爱听那些借口.

屡败屡战,然后,恭喜你,你成功了.

网络编程

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

 ipconfig:查看本机IP

 ping:测试连接

 本地回路地址:127.0.0.1

 IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。已经用尽。 

 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

端口号

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

 端口号范围从0-65535

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

 常用端口

mysql: 3306

oracle: 1521

web: 80

tomcat: 8080

QQ: 4000

feiQ: 2425

网络协议

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

 UDP

面向无连接,数据不安全,速度快。不区分客户端与服务端。

TCP

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

Socket介绍:

Socket套接字,通信的端点

 通信的两端都有Socket。

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

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

Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。

      UDP传输

发送

 创建DatagramSocket

 创建DatagramPacket

 使用DatagramSocket发送DatagramPacket

 关闭DatagramSocket

代码:

import java.net.*;

class UdpSend{

public static void main(String[]args)throws Exception {

//      1,建立udp的socket服务。

DatagramSocket ds = newDatagramSocket(8888);//指定发送端口,不指定系统会随机分配。

//      2,明确要发送的具体数据。

String text = "udp传输演示哥们来了";

byte[] buf = text.getBytes();

//      3,将数据封装成了数据包。

DatagramPacket dp = new DatagramPacket(buf,

buf.length,InetAddress.getByName("10.1.31.127"),10000);

//      4,用socket服务的send方法将数据包发送出去。

ds.send(dp);

//      5,关闭资源。

ds.close();

}

}

接收

 创建DatagramSocket

 创建DatagramPacket

 使用DatagramSocket接收DatagramPacket

关闭DatagramSocke

代码:

class UdpRece {

public static void main(String[] args)throws Exception{

//      1,创建udp的socket服务。

DatagramSocket ds = newDatagramSocket(10000);

//      2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。

byte[] buf = new byte[1024];

DatagramPacket dp = newDatagramPacket(buf,buf.length);

//      3,通过socket服务的接收方法将收到的数据存储到数据包中。

ds.receive(dp);//该方法是阻塞式方法。

//      4,通过数据包的方法获取数据包中的具体数据内容,比如ip,端口,数据等等。

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

int port = dp.getPort();

String text = newString(dp.getData(),0,dp.getLength());//将字节数组中的有效部分转成字符串。

System.out.println(ip+":"+port+"--"+text);

//      5,关闭资源。

ds.close();

}

}

 

TCP传输

两个端点的建立连接后会有一个传输数据的通道,这通道称为流,而且是建立在网络基础上的流,称之为socket流。该流中既有读取,也有写入。

tcp的两个端点:一个是客户端,一个是服务端。

客户端:对应的对象,Socket

服务端:对应的对象,ServerSocket

客户端

 创建Socket连接服务端

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

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

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

客户端

import java.net.*;

import java.io.*;

//需求:客户端给服务器端发送一个数据。

class TcpClient{

public static void main(String[] args) throwsException{

Socket s = newSocket("10.1.31.69",10002);

OutputStream out = s.getOutputStream();//获取了socket流中的输出流对象。

out.write("tcp演示,哥们又来了!".getBytes());

s.close();

}

}

 

服务端

 创建ServerSocket

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

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

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

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

 

class TcpServer{

public static void main(String[] args)throws Exception{

ServerSocket ss = newServerSocket(10002);//建立服务端的socket服务

Socket s = ss.accept();//获取客户端对象

String ip =s.getInetAddress().getHostAddress();

System.out.println(ip+".....connected");

//      可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。

InputStream in = s.getInputStream();//读取客户端的数据,使用客户端对象的socket读取流

byte[] buf = new byte[1024];

int len = in.read(buf);

String text = new String(buf,0,len);

System.out.println(text);

//      如果通讯结束,关闭资源。注意:要先关客户端,在关服务端。

s.close();

ss.close();

}

}

 

练习:

1.   简洁GUI聊天室

package com.itheima.udp.exercise;

 

import java.awt.BorderLayout;

import java.awt.Button;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Frame;

import java.awt.Panel;

import java.awt.Point;

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;

 

public class GUI_Chat extends Frame {

 

         privatestatic final long serialVersionUID = 1L;

        

         privateTextArea viewTextArea = new TextArea();          //用来显示聊天记录的文本域

         privateTextArea sendTextArea = new TextArea(5, 1);   //用来输入消息的文本域(指定行数和列数, 列数由于是边界布局所以无效)

         privateTextField textField = new TextField(20);      //用来输入IP的文本框

         privateButton sendButton = new Button("发送");

         privateButton clearButton = new Button("清屏");

         privateButton logButton = new Button("记录");

         privateButton shakeButton = new Button("震动");

         privatePanel southPanel = new Panel();                                      //放在南边的面板(TextField, 4个Button)

         privatePanel cenerPanel = new Panel();                                      //放在中间的面板(2个TextArea)

 

         privateDatagramSocket socket;

         privateBufferedWriter bw;

        

         /*

          * 构造函数

          */

         publicGUI_Chat() {

                   init();                                                                 //初始化

                   generateSouthPanel();                       // 构造南边的面板

                   generateCenterPanel();                     // 构造中间的面板

                   addListener();                                       // 添加监听器

                   setVisible(true);                                   // 显示

                   newReceiveThread().start();  // 开启接收数据的线程

         }

 

         /*

          * 初始化

          * 设置Frame的标题, 大小, 位置

          * 创建了Socket对象

          */

         privatevoid init() {

                   setTitle("GUI聊天室");

                   setSize(400,600);

                   setLocation(800,50);

                   setMinimumSize(newDimension(400, 300));

                   try{

                            socket= new DatagramSocket();             // 发送端Socket可以不用指定地址(本机)和端口(随机的)

                            bw= new BufferedWriter(new FileWriter("log.txt", true));

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

        

         /*

          * 构造南边的面板

          * 把TextField和4个Button一起放入Panel

          * 把Panel放在南边

          */

         privatevoid generateSouthPanel() {

                   southPanel.add(textField);

                   southPanel.add(sendButton);

                   southPanel.add(clearButton);

                   southPanel.add(logButton);

                   southPanel.add(shakeButton);

                   add(southPanel,BorderLayout.SOUTH);         // 把面板放在Frame的南边

         }

        

         /*

          * 构造中间的面板

          * 把两个TextArea装入Panel

          * 把Panel放在中间

          */

         privatevoid generateCenterPanel() {

                   cenerPanel.setLayout(newBorderLayout());                    // 把面板改为边界布局

                   cenerPanel.add(viewTextArea,BorderLayout.CENTER);        // 用来显示的文本域放在中间

                   cenerPanel.add(sendTextArea,BorderLayout.SOUTH); // 用来发送的文本域放在下面

                   add(cenerPanel,BorderLayout.CENTER);                                   //把整个面板放在Frame的中间

                   viewTextArea.setEditable(false);                                         // 设置为不可编辑, 会改变背景色为灰色

                   viewTextArea.setBackground(Color.WHITE);                    // 设置背景色为白色

         }

        

         /*

          * 给各个组件添加添加监听器

          */

         privatevoid addListener() {

                   addWindowListener(newWindowAdapter() {                                      //关闭窗体时, 释放资源, 退出程序

                            publicvoid windowClosing(WindowEvent e) {

                                     try{

                                               bw.close();

                                               socket.close();

                                               System.exit(0);

                                     }catch (IOException ex) {

                                               ex.printStackTrace();

                                     }

                            }

                   });

                   sendButton.addActionListener(newActionListener() {  // 点击发送按钮时

                            publicvoid actionPerformed(ActionEvent e) {

                                     send();

                            }

                   });

                   clearButton.addActionListener(newActionListener() {

                            publicvoid actionPerformed(ActionEvent e) {

                                     viewTextArea.setText("");

                            }

                   });

                   logButton.addActionListener(newActionListener() {

                            publicvoid actionPerformed(ActionEvent e) {

                                     showLog();

                            }

                   });

                   sendTextArea.addKeyListener(newKeyAdapter() {

                            publicvoid keyPressed(KeyEvent e) {

                                     if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_ENTER ||e.isAltDown() && e.getKeyCode() == KeyEvent.VK_S) {

                                               send();

                                               e.consume();   // 取消这个事件

                                     }

                            }

                   });

                   shakeButton.addActionListener(newActionListener() {

                            publicvoid actionPerformed(ActionEvent e) {

                                     sendShake();

                            }

                   });

         }

 

         privatevoid sendShake() {

                   try{

                            Stringip = textField.getText().trim();

                            DatagramPacketpacket = new DatagramPacket(new byte[] { -1 }, 1, InetAddress.getByName(ip), 20000);

                            socket.send(packet);

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

 

         /*

          * 发送消息

          */

         privatevoid send() {

                   Stringmsg = sendTextArea.getText();              //获取要发送的内容

                   Stringip = textField.getText().trim();                //获取目标地址

                   ip= ip.length() == 0 ? "255.255.255.255" : ip;                  // 如果没填IP, 默认改为群发地址

                  

                   try{

                           DatagramPacketpacket = new DatagramPacket(msg.getBytes(), msg.getBytes().length,InetAddress.getByName(ip), 20000); // 创建Packet

                            Stringtime = getTimeString();                  

                            Stringinfo = time + " 我对 " +(ip.equals("255.255.255.255") ? "所有人" : ip) + " 说:\r\n" +msg + "\r\n\r\n";

                            synchronized(this) {

                                     socket.send(packet);                          // 发送

                                     viewTextArea.append(info);             // 显示发送的内容到TextView

                                     bw.write(info);                                               //保存聊天记录

                            }

                            sendTextArea.setText("");                         // 清空文本域

                            sendTextArea.requestFocus();                  // 控制文本域重新获得焦点

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

        

         /*

          * 获取当前时间字符串

          */

         privateString getTimeString() {

                   Datedate = new Date();

                   SimpleDateFormatsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                   returnsdf.format(date);

         }

        

         /*

          * 用来接收数据的线程

          * 不停地循环接收数据

          * 收到数据后显示到TextArea中

          */

         privateclass ReceiveThread extends Thread {       

                   publicvoid run() {

                            try{

                                     DatagramSocketsocket = new DatagramSocket(20000);

                                     DatagramPacketpacket = new DatagramPacket(new byte[1024 * 1024], 1024 * 1024);

                                     while(true) {

                                               socket.receive(packet);                                                                    //收取数据

                                               byte[]arr = packet.getData();                                                        //获取packet中的数据

                                               intlen = packet.getLength();                                                 //获取长度

                                               if(len == 1 && arr[0] == -1) {

                                                        shake();

                                                        continue;

                                               }

                                               Stringmsg = new String(arr, 0, len);                                    //把字节数据转为String

                                               Stringip = packet.getAddress().getHostAddress();         //从packet中获取发送端的获取IP

                                               Stringtime = getTimeString();                                                        //获取当前时间

                                               Stringinfo = time + " " + ip + " 对我说:\r\n" + msg + "\r\n\r\n";

                                               synchronized(GUI_Chat.this) {                                                      //用外部类对象当作锁对象

                                                        viewTextArea.append(info);    // 显示到TextView

                                                        bw.write(info);                                      //保存聊天记录

                                               }

                                     }

                            }catch (Exception e) {

                                     e.printStackTrace();

                            }

                   }

         }

        

         /*

          * 从文件中读取聊天记录

          * 显示到TextArea中

          */

         privatevoid showLog() {

                   try{

                            bw.flush();                  // 把缓冲区中数据刷出

                           

                            FileInputStreamfis = new FileInputStream("log.txt");

                            ByteArrayOutputStreambaos = new ByteArrayOutputStream();

                            byte[]buffer = new byte[1024];

                            intlen;

                            while((len = fis.read(buffer)) != -1)                    //从文件读取到内存

                                     baos.write(buffer,0, len);

                            fis.close();

                            baos.close();

                           

                            Stringlog = new String(baos.toByteArray());  // 从内存获取数据转为字符串

                            viewTextArea.setText(log);                                                    //显示

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

 

         privatevoid shake() {

                   try{

                            Pointp = getLocation();

                            setLocation(p.x- 20, p.y - 20);

                            Thread.sleep(20);

                            setLocation(p.x+ 20, p.y + 20);

                            Thread.sleep(20);

                            setLocation(p.x+ 20, p.y - 20);

                            Thread.sleep(20);

                            setLocation(p.x- 20, p.y + 20);

                            Thread.sleep(20);

                            setLocation(p);

                   }catch (InterruptedException e) {

                            e.printStackTrace();

                   }

         }

 

         publicstatic void main(String[] args) {

                   newGUI_Chat();

         }

 

}

 

2.   模仿文件上传(要求能断点续传)

客户端:

package com.itheima.tcp.exercise;

 

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.io.OutputStream;

importjava.io.PrintStream;

importjava.net.Socket;

importjava.util.Scanner;

 

public classExercise2_UploadClient {

 

         public static void main(String[] args)throws Exception {

                   // 2.创建Socket, 指定服务端地址和端口, 发起请求

                   Socket socket = newSocket("192.168.1.100", 40000);

                  

                   // 4.获取输入输出流

                   InputStream is =socket.getInputStream();

                   OutputStream os =socket.getOutputStream();

                  BufferedReaderbr = new BufferedReader(new InputStreamReader(is));

                   PrintStream ps = newPrintStream(os);

                  

                   // 5.从键盘输入读取一个文件路径, 验证是否存在, 是否是文件夹

                   File file = getFile();

                  

                   // 6.把文件名和文件大小发送到服务端

                   ps.println(file.getName());

                   ps.println(file.length());

                  

                   // 8.接收结果, 如果已存在给予提示, 程序退出

                   String result =br.readLine();

                   if ("存在".equals(result)) {

                            System.out.println("文件已存在, 请不要重复上传!");

                            return;

                   }

                  

                   // 9.定义输入流指向文件, 读取文件写出到网络

                   FileInputStream fis = newFileInputStream(file);    

                   long filelength =Long.parseLong(result);        // 服务端已完成的大小

                   fis.skip(filelength);                                                 //上次完成了多少就跳过多少

                  

                   byte[] buffer = newbyte[1024];

                   int len;

                   while ((len =fis.read(buffer)) != -1)          // 读取文件

                            os.write(buffer, 0,len);                               // 写到网络

                   fis.close();

                  socket.close();

                   System.out.println("上传完毕!");

         }

        

         private static File getFile() {

                   System.out.println("请输入要上传的文件路径:");

                   Scanner scanner = newScanner(System.in);

                   while (true) {

                            File file = newFile(scanner.nextLine());

                            if (!file.exists())

                                     System.out.println("您输入的路径不存在, 请重新输入:");

                            else if(file.isDirectory())

                                     System.out.println("暂不支持文件夹上传, 请输入一个文件路径:");

                            else

                                     returnfile;

                   }

         }

 

}

 -------------------------------------------------------------------------------==

服务端:

packagecom.itheima.tcp.exercise;

 

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.io.OutputStream;

importjava.io.PrintStream;

importjava.net.ServerSocket;

importjava.net.Socket;

 

 

public classExercise2_UploadServer {

 

         public static void main(String[] args)throws Exception {

                   // 1.创建ServerSocket, 定义循环, 循环中接收客户端请求, 开启新线程

                   ServerSocket serverSocket =new ServerSocket(40000);

                   while (true) {

                            final Socket socket= serverSocket.accept();

                           

                            new Thread(){

                                     public voidrun() {

                                               try{

                                                        //3.获取输入输出流

                                                        InputStreamis = socket.getInputStream();

                                                        OutputStreamos = socket.getOutputStream();

                                                        BufferedReaderbr = new BufferedReader(new InputStreamReader(is));

                                                        PrintStreamps = new PrintStream(os);

                                                       

                                                        //7.接收文件名和文件大小, 查找文件是否存在, 是否已完成上传

                                                        Stringfilename = br.readLine();

                                                        longfilelength = Long.parseLong(br.readLine());

                                                       

                                                        Filefile = new File("F:/Upload", filename);

                                                        if(file.exists() && file.length() == filelength) {

                                                                 ps.println("存在");

                                                                 return;

                                                        }else {

                                                                 ps.println(file.length());   // 写回文件大小(0或已完成的大小)

                                                        }

                                                       

                                                        Stringip = socket.getInetAddress().getHostAddress();

                                                        System.out.println(ip+ (file.exists() ? " 断点续传: " :" 开始上传: ") +filename);

                                                        longstart = System.currentTimeMillis();

                                                       

                                                        //10.定义输出流指向文件, 从网络中读取数据写出到文件

                                                        FileOutputStreamfos = new FileOutputStream(file, true);

                                                        byte[]buffer = new byte[1024];

                                                        intlen;

                                                        while((len = is.read(buffer)) != -1)            //读取网络

                                                                 fos.write(buffer,0, len);                              // 写出文件

                                                        fos.close();

                                                        socket.close();

                                                       

                                                        longstop = System.currentTimeMillis();

                                                        System.out.println(ip+ " 上传完毕: " + filename+ ", 耗时: " + (stop -start) + "毫秒.");

                                               }catch (IOException e) {

                                                        e.printStackTrace();

                                               }

                                     }

                            }.start();

                   }

         }

}

 

                                               ------- android培训java培训、期待与您交流! ----------

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值