JAVA网络编程,UDP和TCP本机通讯

来源:互联网 发布:数据挖掘 量化分析 编辑:程序博客网 时间:2024/06/13 18:08

这里写图片描述

根据day26视频敲写

UDP利用线程实现发送和接收

package com.tanz.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Demo1_udp {
/**
*
* 此类描述的是:用多线程将发送和接收用同一个窗口完成
* @author:
* @version:1.0
* @date:2017年5月4日 下午2:18:52
*/
public static void main(String[] args) {

    new Receive().start();    new Send().start();}

}

class Receive extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(6666); // 创建Socket相当于创建码头,指定端口号6666
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);// 创建Packet相当于创建集装箱

        while (true) {            socket.receive(packet); // 接货,接收数据            byte[] arr = packet.getData(); // 获取数据            int len = packet.getLength(); // 获取有效的字节个数            String ip = packet.getAddress().getHostAddress(); // 获取ip地址            int port = packet.getPort(); // 获取端口号            System.out.println(ip + ":" + port + ":" + new String(arr, 0, len));        }    } catch (IOException e) {        e.printStackTrace();    }}

}

class Send extends Thread {
public void run() {
try {
Scanner sc = new Scanner(System.in); // 创建键盘录入对象
DatagramSocket socket = new DatagramSocket(); // 创建Socket相当于创建码头

        while (true) {            String line = sc.nextLine(); // 获取键盘录入的字符串            if ("quit".equals(line)) {                break;            }            DatagramPacket packet = // 创建Packet相当于集装箱                    new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"),                            6666);            socket.send(packet); // 发货,将数据发出去        }        socket.close();    } catch (IOException e) {        e.printStackTrace();    }}

}


UDP 自问自答聊天室

package com.tanz.udp;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo2_GUIChat extends Frame{
private TextField tf;
private Button send;
private Button log;
private Button clear;
private Button shake;
private TextArea viewText;
private TextArea sendText;
private DatagramSocket socket;
private BufferedWriter bw;
/**
* @param args
* GUI聊天
*/
public Demo2_GUIChat() {
init();
southPanel();
centerPanel();
event();
}

public void event() {    this.addWindowListener(new WindowAdapter() {        @Override        public void windowClosing(WindowEvent e) {            try {                socket.close();                bw.close();            } catch (IOException e1) {                e1.printStackTrace();            }            System.exit(0);        }    });    send.addActionListener(new ActionListener() {        @Override        public void actionPerformed(ActionEvent e) {            try {                send();            } catch (IOException e1) {                e1.printStackTrace();            }        }    });    log.addActionListener(new ActionListener() {        @Override        public void actionPerformed(ActionEvent e) {            try {                logFile();            } catch (IOException e1) {                e1.printStackTrace();            }        }    });    clear.addActionListener(new ActionListener() {        @Override        public void actionPerformed(ActionEvent e) {            viewText.setText("");        }    });    shake.addActionListener(new ActionListener() {        @Override        public void actionPerformed(ActionEvent e) {            try {                send(new byte[]{-1},tf.getText());            } catch (IOException e1) {                e1.printStackTrace();            }        }    });    sendText.addKeyListener(new KeyAdapter() {        @Override        public void keyReleased(KeyEvent e) {            //if(e.getKeyCode() == KeyEvent.VK_ENTER && e.isControlDown()) {    //isControlDown ctrl是否被按下            if(e.getKeyCode() == KeyEvent.VK_ENTER) {                try {                    send();                } catch (IOException e1) {                    e1.printStackTrace();                }            }        }    });}private void shake() {    int x = this.getLocation().x;                           //获取横坐标位置    int y = this.getLocation().y;                           //获取纵坐标位置    for(int i = 0; i < 20; i++) {        try {            this.setLocation(x + 20, y + 20);            Thread.sleep(20);            this.setLocation(x + 20, y - 20);            Thread.sleep(20);            this.setLocation(x - 20, y + 20);            Thread.sleep(20);            this.setLocation(x - 20, y - 20);            Thread.sleep(20);            this.setLocation(x, y);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}private void logFile() throws IOException {    bw.flush();                                 //刷新缓冲区    FileInputStream fis = new FileInputStream("config.txt");    ByteArrayOutputStream baos = new ByteArrayOutputStream();   //在内存中创建缓冲区    int len;    byte[] arr = new byte[8192];    while((len = fis.read(arr)) != -1) {        baos.write(arr, 0, len);    }    String str = baos.toString();               //将内存中的内容转换成了字符串    viewText.setText(str);    fis.close();}private void send(byte[] arr, String ip) throws IOException {    DatagramPacket packet =             new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), 9999);    socket.send(packet);                        //发送数据}private void send() throws IOException {    String message = sendText.getText();        //获取发送区域的内容    String ip = tf.getText();                   //获取ip地址;    ip = ip.trim().length() == 0 ? "255.255.255.255" : ip;    send(message.getBytes(),ip);    String time = getCurrentTime();             //获取当前时间    String str = time + " 我对:" + (ip.equals("255.255.255.255") ? "所有人" : ip) + "说\r\n" + message + "\r\n\r\n";  //alt + shift + l 抽取局部变量    viewText.append(str);                       //将信息添加到显示区域中    bw.write(str);                              //将信息写到数据库中    sendText.setText("");}private String getCurrentTime() {    Date d = new Date();                        //创建当前日期对象    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");    return sdf.format(d);                       //将时间格式化}public void centerPanel() {    Panel center = new Panel();                 //创建中间的Panel    viewText = new TextArea();    sendText = new TextArea(5,1);    center.setLayout(new BorderLayout());       //设置为边界布局管理器    center.add(sendText,BorderLayout.SOUTH);    //发送的文本区域放在南边    center.add(viewText,BorderLayout.CENTER);   //显示区域放在中间    viewText.setEditable(false);                //设置不可以编辑    viewText.setBackground(Color.WHITE);        //设置背景颜色    sendText.setFont(new Font("xxx", Font.PLAIN, 15));    viewText.setFont(new Font("xxx", Font.PLAIN, 15));    this.add(center,BorderLayout.CENTER);}public void southPanel() {    Panel south = new Panel();                  //创建南边的Panel    tf = new TextField(15);    tf.setText("127.0.0.1");    send = new Button("send");    log = new Button("history");    clear = new Button("clear");    shake = new Button("shake");    south.add(tf);    south.add(send);    south.add(log);    south.add(clear);    south.add(shake);    this.add(south,BorderLayout.SOUTH);         //将Panel放在Frame的南边}public void init() {    this.setLocation(500, 50);    this.setSize(400, 600);    new Receive().start();    try {        socket = new DatagramSocket();        bw = new BufferedWriter(new FileWriter("config.txt",true)); //需要在尾部追加    } catch (Exception e) {        e.printStackTrace();    }    this.setVisible(true);}private class Receive extends Thread {          //接收和发送需要同时执行,所以定义成多线程的    public void run() {        try {            DatagramSocket socket = new DatagramSocket(9999);            DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);            while(true) {                socket.receive(packet);             //接收信息                byte[] arr = packet.getData();      //获取字节数据                int len = packet.getLength();       //获取有效的字节数据                if(arr[0] == -1 && len == 1) {      //如果发过来的数组第一个存储的值是-1,并且数组长度是1                    shake();                        //调用震动方法                    continue;                       //终止本次循环,继续下次循环,因为震动后不需要执行下面的代码                }                String message = new String(arr,0,len); //转换成字符串                String time = getCurrentTime();     //获取当前时间                String ip = packet.getAddress().getHostAddress();   //获取ip地址                String str = time + " " + ip + " 对我说:\r\n" + message + "\r\n\r\n";                viewText.append(str);                bw.write(str);            }        } catch (Exception e) {            e.printStackTrace();        }    }}public static void main(String[] args) {    new Demo2_GUIChat();}

}


TCP client与server本机实现通讯

package com.tanz.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo2_Client {

/** * * 1.客户端    * 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器    * 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流    * 输入流可以读取服务端输出流写出的数据    * 输出流可以写出数据到服务端的输入流 * @throws IOException  * @throws UnknownHostException  */public static void main(String[] args) throws UnknownHostException, IOException {    Socket socket = new Socket("127.0.0.1", 12345);    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));     //将字节流包装成了字符流    PrintStream ps = new PrintStream(socket.getOutputStream());                 //PrintStream中有写出换行的方法    System.out.println(br.readLine());    ps.println("我不信");    System.out.println(br.readLine());    ps.println("呸!辣鸡游戏,毁我青春,耗我钱财!");    socket.close();}

}



package com.tanz.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo2_Server {

/** * * 2.服务端* 创建ServerSocket(需要指定端口号)* 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket* 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流* 输入流可以读取客户端输出流写出的数据* 输出流可以写出数据到客户端的输入流 * @throws IOException  */public static void main(String[] args) throws IOException {    ServerSocket server = new ServerSocket(12345);    while(true) {        final Socket socket = server.accept();                      //接受客户端的请求        new Thread() {            public void run() {                try {                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));     //将字节流包装成了字符流                    PrintStream ps = new PrintStream(socket.getOutputStream());                 //PrintStream中有写出换行的方法                    ps.println("我半藏中单贼6");                    System.out.println(br.readLine());                    ps.println("来solo");                    System.out.println(br.readLine());                    socket.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }.start();    }}

}

总结

java网络编程三大要素:IP,端口,协议

IP:

  1. ipconfig:查看本机IP192.168.12.42
  2. ping:测试连接192.168.40.62
  3. 本地回路地址:127.0.0.1 255.255.255.255是广播地址
  4. IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
  5. IPv6:8组,每组4个16进制数。

端口:

*每个程序在设备上的唯一标识
* 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。
* 端口号范围从0-65535
* 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
* 常用端口
* mysql: 3306
* oracle: 1521
* web: 80
* tomcat: 8080
* QQ: 4000

协议:
* 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
* UDP
* 面向无连接,数据不安全,速度快。不区分客户端与服务端。
* TCP
  * 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
* 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据 (三次握手,1请求,1响应,1传输数据)

网络编程(Socket)
* Socket套接字概述:
* 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
* 通信的两端都有Socket。
* 网络通信其实就是Socket间的通信。
* 数据在两个Socket间通过IO流传输。
* Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。

0 0