zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

网络编程

2023-09-14 08:58:30 时间
网络编程三要素:
    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类:前3号段为网络号段+后一段的主机号段
            一个网络号:256
            
    两个DOS命令:
        ipconfig:查看本机地址
        ping 后面跟ip地址:测试本机与指定的IP地址间的通信是否有问题
        
    特殊的ip地址
        127.0.0.1 回环地址(表示本机)
        x.x.x.255广播地址
        x.x.x.0网络地址
        
为了方便使用IP,java提供InetAccess
    
端口:
    正在运行的程序的标识
    有效端口:0~65535,其中0~1024系统使用或者保留。可以使用360查看各个程序的端口
            

协议:
    通信的规则
    
    UDP:
        把数据打包
        数据有限制64k
        不建立连接
        速度快
        不可靠
        
    TCP:
        建立连接通道
        数据无限制
        速度慢
        可靠
        
    举例:
        UDP:发短信
        TCP:打电话
    

InetAccess:

package com.gz_02;

import java.net.InetAddress;
import java.net.UnknownHostException;

/*
 * 如果一个类没有构造方法:
 *     A:成员方法全部是静态的
 *     B:单例模式
 *     C:类中有静态方法返回该类的对象
 * 
 * 
 * 看InetAddress的成员方法:
 *     public static InetAddress getByName(String host) 根据主机名或者IP地址的字符串表示得到I[地址对象
 */
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress address=InetAddress.getByName("192.168.1.100");
        
        //publicStringgetHostName()
        String name=address.getHostName();
        
        //public String getHostAddress()
        String ip=address.getHostAddress();
        
        System.out.println(name+"---"+ip);
    }
}
View Code

UDP:

package com.gz_03;

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

/*
 * UDP协议接受数据:
 *     A:创建发送端Socket对象
 *     B:创建一个数据包(接受容器)
 *     C:调用Socket对象的接受方法接受方法
 *     D:解析数据包并显示在数据台
 *     D:释放资源
 *
 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        //创建Socket对象
        //DatagramSocket(int port)
        DatagramSocket ds=new DatagramSocket(10670);
        
        //创建一个数据包(接受容器)
        //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);
        
        //接受到了数据要显示下
        //解析数据包,并显示在数据台
        //byte[] getData()
        //int getLength()获取数据长度
        byte[] bys2=dp.getData();
        int len=dp.getLength();
        String s=new String(bys2,0,len);
        //获取对方ip
        //public InetAddress getAddress()
        InetAddress address=dp.getAddress();
        String ip=address.getHostAddress();
        System.out.println(ip+":"+s);
        
        //释放资源
        ds.close();
    }

}
package com.gz_03;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/*
 * UDP协议发送数据:
 *     A:创建发送端Socket对象
 *     B:创建数据,并把数据打包
 *     C:调用Socket对象的发送方法发送数据包
 *     D:释放资源
 */
public class SendDemo {
    public static void main(String[] args) throws IOException {
        //创建发送端Socket对象
        //DatagrameSocket()
        DatagramSocket ds=new DatagramSocket();
        
        //创建数据,并把数据打包
        //DatagramPacket(byte[] buf,int length,InetAddress address,int port)
        
        //创建数据
        byte[] bys="我是郭祯".getBytes();
        //长度
        int length=bys.length;
        //IP地址对象
//        InetAddress address=InetAddress.getByName("192.168.1.129");
        InetAddress address=InetAddress.getByName("192.168.1.129");
        //端口
//        int port=6000;
        int port=10670;
        DatagramPacket dp=new DatagramPacket(bys, length, address, port);
        //调用Socket对象的发送方法发送数据包
        //public void send(DatagreamPacket p)
        ds.send(dp);
        
        //释放资源
        ds.close();
    }
}
View Code

UDP简单聊天:

package com.gz_06;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;
/*
 * UDP协议发送数据:
 *     A:创建发送端Socket对象
 *     B:创建数据,并把数据打包
 *     C:调用Socket对象的发送方法发送数据包
 *     D:释放资源
 */
public class SendThread implements Runnable {
    private DatagramSocket ds;
    public SendThread(DatagramSocket ds){
        this.ds=ds;
    }
    @Override
    public void run() {    
        try{
            while(true){
                Scanner input=new Scanner(System.in);
                String str=input.nextLine();
                DatagramPacket dp=null;
                try {
                    dp=new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("192.168.1.100"), 12306);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ds.send(dp);
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            ds.close();
        }
        
        
    }

}
package com.gz_06;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
 * UDP协议接受数据:
 *     A:创建发送端Socket对象
 *     B:创建一个数据包(接受容器)
 *     C:调用Socket对象的接受方法接受方法
 *     D:解析数据包并显示在数据台
 *     D:释放资源
 *
 */
public class ReceieveThread implements Runnable {
    private DatagramSocket ds;
    public ReceieveThread(DatagramSocket ds){
        this.ds=ds;
    }
    @Override
    public void run() {
        try{
            while(true){
                byte[] buff=new byte[1024];
                DatagramPacket dp=new DatagramPacket(buff, buff.length);
                ds.receive(dp);
                byte[] b=dp.getData();
                InetAddress ia=dp.getAddress();
                String ip=ia.getHostAddress();
                System.out.println(ip+":"+new String(b,0,dp.getLength()));
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            ds.close();
        }
        
    }

}
package com.gz_06;

import java.io.IOException;
import java.net.DatagramSocket;

public class CharRoom {
    public static void main(String[] args) throws IOException{
        DatagramSocket st=new DatagramSocket();
        DatagramSocket ds=new DatagramSocket(12306);
        
        SendThread sd=new SendThread(st);
        ReceieveThread re=new ReceieveThread(ds);
        
        new Thread(sd).start();
        new Thread(re).start();
    }

}
View Code

TCP:

package com.gz_07;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
 * A:创建发送端的Socket对象
 *     这一步如果成功,就说明连接已经成功了
 * B:获取输出流,写数据
 * C:释放资源
 *
 *Connection refused
 *连接被拒绝。tcp一定要服务器被开启,因为tcp要建立连接
 *而ucp不需要,ucp不保证数据一定过去对面接收到
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建发送端的Socket对象
        //Socket(InetAdderss address,int port)
        //Socket(String host,int port)
        Socket s=new Socket("192.168.1.100",8888);
        
        //获取输出流,写数据
        OutputStream os=s.getOutputStream();
        os.write(("hello,tcp,我来了").getBytes());
        InputStream in=s.getInputStream();
        byte[] b=new byte[1024];
        int t=in.read(b);//阻塞式
        String str=new String(b,0,t);
        System.out.println(str);
        
        s.close();
    }
}
package com.gz_07;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * TCP协议接受数据
 *     A:创建接收端的Socket对象
 *     B:监听客户端连接返回一个对应的Socket对象
 *     C:获取输入流读取数据,显示在控制台
 *     D:释放资源
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //ServerSocket(port)
        ServerSocket s=new ServerSocket(8888);
        
        Socket ss=s.accept();//阻塞式方法,侦听并接受到此套间的连接,返回对应的Socket对象
        
        InputStream is=ss.getInputStream();
        
        byte[] bys=new byte[1024];
        int len=is.read(bys);
        String str=new String(bys,0,len);
        String str1=ss.getInetAddress().getHostAddress();
        System.out.println(str1+":"+str);
        OutputStream os=ss.getOutputStream();
        os.write("收到了".getBytes());
        ss.close();
        //s.close();服务器不应该关闭
    }
}
View Code

关于反馈:

package com.gz_08;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo02 {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(8888);
        
        Socket s=ss.accept();//阻塞式 排除
        System.out.println(s.getInetAddress().getHostAddress());
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bw=new BufferedWriter(new FileWriter("copy.txt"));
        String line=null;
        while((line=br.readLine())!=null){
            //阻塞式 阻塞了 无法判断得到的输入流是否是结束的,所以一直在等待,怎么办呢?
            //方式一:自定义一个结束标记,这里收到结束标记就不等待了。自定义结束标记如果文件中存在自定义结束标记就会出问题。其他还好
            //方式二:java api提供了一个方法s.shutdownOutput(); 写入关闭,也就是完成
//            if("over".equals(line)){
//                break;
//            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        
        //接受到了数据,我希望给出一个反馈
        OutputStream os=s.getOutputStream();
        os.write("完成上传!".getBytes());
        
        //经过测试,我们发现:程序不是按照我们想要的流程走。它迟迟不给出反馈。这是为什么呢?我们有几个阻塞式方法,问题肯定是出现在那里的
        //判断是在这里的while循环的read方法处阻塞了
        s.close();
    }
}
package com.gz_08;

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;
import java.net.UnknownHostException;

public class ClientDemo02 {
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket s=new Socket("192.168.1.100",8888);
        
        BufferedReader br=new BufferedReader(new FileReader("src/网络编程三要素"));
        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();
        s.shutdownOutput();//写入完成
        
        BufferedReader fr=new BufferedReader(new InputStreamReader(s.getInputStream()));
        byte[] b=new byte[1024];
        String str=fr.readLine();
        System.out.println(str);
        br.close();
        bw.close();
    }
}
View Code

多线程模拟:

package com.gz_09;

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.1.100", 11101);

        // 封装文本文件
        // BufferedReader br = new BufferedReader(new FileReader(
        // "InetAddressDemo.java"));
        BufferedReader br = new BufferedReader(new FileReader(
                "TCP编程"));
        // 封装通道内流
        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();
    }
}
package com.gz_09;

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(11101);

        while (true) {
            Socket s = ss.accept();
            new Thread(new UserThread(s)).start();
        }
    }
}
package com.gz_09;

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();
        }
    }

}
View Code

 前面一直以为使用TCP同一个Socket不可以多次通信。现在发现单纯使用flush方法不使用shutdownInput或者shutdownOutput也可以在服务器读取多次并回复多次。

代码:

package com.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import com.hh.ReadDemo;
import com.hh.WriterDemo;

public class ClientDemo {
    /**
     * 项目需求分析:
     *     客户端发送数据支持对线程,所以服务器接收数据也应该是多线程
     * 现在主要是想测试一下直接使用一个Tcp进行聊天并且多条语句
     */
    private Socket s=null;
    DataInputStream dis=null;
    DataOutputStream dos=null;
    public static void main(String[] args) {
        ClientDemo cd=new ClientDemo();
        cd.init();
        System.out.println("可以和服务器进行交流了");
        //while(true){ 不能新建太多线程,所以我尝试将while循环卸载线程的run方法
            new Thread(new ReadDemo(cd.s)).start();
            new Thread(new WriterDemo(cd.s)).start();
        //}
        
    }
    public void init(){
        try {
            s=new Socket("127.0.0.1",8888);
            dis=new DataInputStream(s.getInputStream());
            dos=new DataOutputStream(s.getOutputStream());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
//    public void write(){
//        Scanner sc=new Scanner(System.in);
//        String s=sc.next();
//        try {
//            dos.writeUTF(s);
//            dos.flush();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//    public void read(){
//        try {
//            String s=dis.readUTF();
//            System.out.println(s);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
    
}
package com.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import com.hh.ReadDemo;
import com.hh.WriterDemo;

public class ServerDemo {
    public static void main(String[] args) {
        try {
            ServerSocket server=new ServerSocket(8888);
            Socket s=server.accept();
            //while(true){
                new Thread(new ReadDemo(s)).start();
                new Thread(new WriterDemo(s)).start();
            //}
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.hh;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class ReadDemo implements Runnable{
    private Socket s;
    private DataInputStream dis=null;
    private DataOutputStream dos=null;
    public ReadDemo(Socket s){
        this.s=s;
        try {
            dis=new DataInputStream(s.getInputStream());
            dos=new DataOutputStream(s.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        try {
            while(true){
                String str=dis.readUTF();
                System.out.println(str);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
package com.hh;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class WriterDemo implements Runnable{
    private Socket s;
    private DataInputStream dis=null;
    private DataOutputStream dos=null;
    public WriterDemo(Socket s){
        this.s=s;
        try {
            dis=new DataInputStream(s.getInputStream());
            dos=new DataOutputStream(s.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        while(true){
            Scanner sc=new Scanner(System.in);
            try {
                String str=sc.next();
                dos.writeUTF(str);
                dos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }
}
View Code