网络编程

软件结构

C/S结构:Cilent/Server结构,是指客户端和服务器,例如QQ。

B/S结构:Browser/Server结构,是指浏览器和服务器结构,例如火狐。

网络编程:一定的协议下,实现两台计算机的通信的程序

网络通信协议

计算机进行连接和通讯需要遵守一定的规则,就是网络通信协议。

TCP/IP协议(传输控制协议/因特网互联协议Transmission Control Protocol/Internet Protocol)最基本的协议,定义了

计算机如何连入因特网,以及数据如何在他们之间传输的标准。

协议分类

UDP:用户数据报协议(User Datagram Protocol),无连接通讯协议,耗资源小,效率高,但容易丢包。例如QQ。

TCP: 传输控制协议(Transmission Control Protocol),面向连接的通讯协议,传送数据前,客户端和服务器三次握手。第一次握手:客户端向服务器端发送连接请求,第二次握手:服务器端回应收到,第三次握手:客户端再次发送信息确认连接。例如文件的下载,网页的浏览。安全,但效率不太高。

网络编程三要素

协议

规则

IP地址

IPv4:是一个32位的二进制,通常被分为4个字节,例如192.168.65.100,最多42亿个。

常用命令:ipconfig

检查网络是否连接:ping 220.181.57.210

本机ip地址:ping 127.0.0.1   ping localhost

端口号:是一个逻辑端口,当我们使用网络软件一打开,那么操作系统就会为网络软件分配一个随机的端口号,或者软件打开的时候和系统要指定的端口号,端口号是由两个字节组成,取值范围在0-65535之间。1024之前的端口号已经无法使用。例如:192.168.1.200:5000。

常用的端口号: 1.80端口号     www.baidu.com:80

                          2.数据库    mysql:3306    oracle:1521

                          3.Tomact:8080

Socket

Socket就是为了网络服务提供的一种机制

通讯的两端都有Socket

网络通讯其实就是Socke间的通讯

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

UPD通讯

DatagramSocket

此类表示用于发送和接收数据报数据包的套接字。

构造数据报套接字并将其绑定到本地主机上的任何可用端口。

DatagramPacket

数据报包用于实现无连接分组传送服务。 仅基于该数据包中包含的信息,每个消息从一台机器路由到另一台机器。 从一台机器发送到另一台机器的多个分组可能会有不同的路由,并且可能以任何顺序到达。 包传送不能保证。

发送端

package com.monfolld.net.UPD;


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

public class UDPSendDemo {
    public static void main(String[] args)throws IOException {
        System.out.println("发送端启动....");
        /*创建UPD传输的发送端
        * 思路:
        * 1.创建upd的socket服务
        * 2.将要发送的数据封装到数据包中
        * 3.通过upd的socket服务将数据包发送出去
        * 4.关闭socket服务*/
        DatagramSocket ds=new DatagramSocket(8888);
        String str="upd输出演示:哥们来了";
        byte[] buf=str.getBytes();

        DatagramPacket dp=new DatagramPacket(buf,buf.length, InetAddress.getByName("169.254.12.142"),10000);
        ds.send(dp);
        ds.close();
    }
}

 接收端

package com.monfolld.net.UPD;

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

public class UDPReceDemo {
    public static void main(String[] args)throws IOException {
        System.out.println("接收端启动....");
        /*建立UDP接收端的思路:
        * 1.检录udp,socket服务
        * 2.创建数据包,用于存储接收到的数据,方便用数据包对象的方法解析这些数据
        * 3.使用socket服务的receive方法将接收到的数据存储到数据包中
        * 4.通过数据包的方法解析数据包中的数据
        * 5.关闭资源
        **/
        DatagramSocket ds=new DatagramSocket(10000);
        byte[] buf=new byte[1024];
        DatagramPacket dp=new DatagramPacket(buf,buf.length);
        System.out.println("接收端启动....");
        ds.receive(dp);
        System.out.println("接收端启动....");
        String ip=dp.getAddress().getHostAddress();
        int prot=dp.getPort();
        String text=new String(dp.getData(),0,dp.getLength());

        System.out.println(ip+":"+prot+":"+text);
        ds.close();
    }
}

聊天程序

发送端类

package com.monfolld.net.UPD;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPSendTest implements Runnable {
    private DatagramSocket ds;
    public UDPSendTest(DatagramSocket ds){
        this.ds=ds;
    }
    public void run(){
        try {
            DatagramSocket ds=new DatagramSocket(8888);
            BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
            String line=null;
            while ((line=bufr.readLine())!=null){
                byte[] buf=line.getBytes();
                DatagramPacket dp=new DatagramPacket(buf,buf.length, InetAddress.getByName("169.254.12.142"),10000);
                ds.send(dp);
            }
        }catch (Exception e){
        }
    }
}

 接收端类

package com.monfolld.net.UPD;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPReceTest implements Runnable{
    private DatagramSocket ds;
    public UDPReceTest(DatagramSocket ds){
        this.ds=ds;
    }
    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();
                int prot=dp.getPort();
                String text=new String(dp.getData(),0,dp.getLength());
                System.out.println(ip+":"+prot+":"+text);
            }
        }catch (Exception e){
        }
    }
}

聊天室

package com.monfolld.net.UPD;

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

public class ChatDemo {
    public static void main(String[] args)throws IOException {
        DatagramSocket send=new DatagramSocket();
        DatagramSocket rece=new DatagramSocket(10000);
        new Thread(new UDPSendTest(send)).start();
        new Thread(new UDPReceTest(rece)).start();
    }
}

TCP通讯程序

 客户端代码实现

package com.monfolld.net;

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

/*TCP通讯的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器会写的数据
* 表示客户端的类:
* java.net.Socket:此类实现客户端套接字,套接字是两台机器通讯的端点
* 套接字:包含了IP地址和编口号的网路单位
*
* 构造方法:
*   Socket(String host, int port)
    创建流套接字并将其连接到指定主机上的指定端口号。
*   参数:服务器主机的名称/服务器的IP地址,服务器的端口号
* 成员方法:
*   OutoutStream getOutputStream();
*   InputStream getInputStream();
*   void close();//关闭套接字
*  实现步骤:
*   1.创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号
*   2.使用Socket对象中的getOutputStream()获取网络字节输出流OutoutStream对象
*   3.使用网络字节输出流OutoutStream对象中的write,给服务器发送数据
*   4.使用Socket对象中的getInputStream()获取网络字节输出流InputStream对象
*   5.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据
*   6.释放资源(Socket)
* 注意:
*   1.客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
*   2.当我们创建客户端对象Socket的时候,就会请求服务器和服务器经过三次握手建立连接通路,
*   这时如果服务器没有启动,那么久会抛出异常*/
public class TCPCilent {
    public static void main(String[] args)throws IOException {
        Socket socket=new Socket("127.0.0.1",8888);
        OutputStream os=socket.getOutputStream();
        os.write("你好服务器".getBytes());
        InputStream is=socket.getInputStream();
        byte[] bytes=new byte[1024];
        int len=is.read(bytes);
        System.out.println(new String(bytes,0,len));
        socket.close();
    }
}

服务器端代码实现

package com.monfolld.net;

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

/*TCP通讯的服务器端:接收客户端的请求,读取客户端发送的数据,给客户端回写数据
* 表示服务器的类:java.net.ServerSocket此类实现服务器套接字
*
* 构造方法:
* ServerSocket(int port)创建绑定到指定端口的服务器套接字。
*服务器必须明确知道哪个客户端请求的服务器,所以可以使用accept方法获取请求到的客户端对象Socket
* 成员方法:
* Socket accept()侦听并接受此套接字的连接
* 服务器的实现步骤:
*   1.创建服务器ServerSocket对象和系统要指定的端口号
*   2.使用ServerSocket对象中的accept,获取到请求的客户端对象Socket
*   3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
*   4.使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据
*   5.使用Socket对象中的方法getOutoutStream()获取网络字节输出流OutputStream对象
*   6.使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据
*   7.释放资源(Socket)*/
public class TCPServer {
    public static void main(String[] args)throws IOException {
        ServerSocket serverSocket=new ServerSocket(8888);
        Socket socket=serverSocket.accept();
        InputStream is=socket.getInputStream();
        byte[] bytes=new byte[1024];
        int len=is.read(bytes);
        System.out.println(new String(bytes,0,len));
        OutputStream os=socket.getOutputStream();
        os.write("收到谢谢".getBytes());
        socket.close();
        serverSocket.close();
    }
}

文件上传案例

  客户端代码实现

package com.monfolld.net.FileUpload;

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

/*文件上传案例的客户端:读取本地文件,上传到服务器,读取服务器回写的数据
* 明确:
*   数据源:d:\\1.jpg
*   目的地:服务器
* 实现步骤:
*   1.创建一个本地字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
*   2.创建一个客户端Socket对象,构造方法中绑定服务器的IP地址和端口号
*   3.使用Socket中的方法getOutputStream,获取网络字节输出流OutputStream对象
*   4.使用本地字节输入流FileInputStream对象中的方法read,读取本地文件
*   5.使用网络字节输出流OutputStream对象中的方法write,把读取到的文件上传到服务器
*   6.使用Socket中的方法getInputStream,获取网络字节输入流InputStream对象
*   7.使用网络字节输入流InputStream对象中的方法read读取服务回写的数据
*   8.释放资源*/
public class TCPClient {
    public static void main(String[] args)throws IOException {
        FileInputStream fis=new FileInputStream("d:\\1.txt");
        Socket socket=new Socket("127.0.0.1",8888);
        OutputStream os=socket.getOutputStream();
        int len=0;
        byte[] bytes=new byte[1024];
        while ((len=fis.read(bytes))!=-1){  //read()读取本地上传文件,结束标记是-1
            os.write(bytes,0,len);  //但while循环不会读取到-1,那么也不会把结束标识写给服务器
        }                           //所以需要shutdownOutput(禁用此套接字的输出流)方法结束
                                        
        socket.shutdownOutput();//上传完以后,终止read读取不停止,防止while进入死循环
        InputStream is=socket.getInputStream();

        while ((len=is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        fis.close();
        socket.close();

    }
}

服务器端代码实现

package com.monfolld.net.FileUpload;

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

/*文件上传案例服务器端:读取客户端上传的文件,保存到服务器的硬盘,给客户端回写"上传成功"
明确:
    数据源:客户端上传的文件
    目的地:服务器的硬盘 d:\\upload\\1.jpg
实现步骤
    1.创建一个服务器ServerSocket对象,和系统要指定的端口号
    2.使用ServerSocket对象中的方法accept,获取到请求的客户端Scoket对象
    3.使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
    4.判断d:\\upload文件夹是否存在,不存在则创建
    5.创建一个本地字节输出流FileOutputStream对象,构造方法中绑定要输出的目的地
    6.使用网络字节输入流InputStream中的方法read,读取客户端上传的文件
    7.使用本地字节输出流FileOutputStream对象中的方法write,吧独到的文件保存到服务器的硬盘上
    8.使用Scoket对象中的getOutputStream,获取到网络字节输出流OutputStream对象
    9.使用网咯字节输出流OutputStream对象中的方法write,给客户端回写"上传成功"
    10.释放资源(FileOutoutStream,Socket,ServerSocket)
*/
public class TCPServer {
    public static void main(String[] args)throws IOException {
        ServerSocket serverSocket=new ServerSocket(8888);
        Socket socket=serverSocket.accept();
        InputStream is=socket.getInputStream();
        File file=new File("d:\\upload");
        if (!file.exists()){
            file.mkdirs();
        }
        FileOutputStream fos=new FileOutputStream(file+"\\1.txt");
        int len=0;
        byte[] bytes=new byte[1024];
        while ((len=is.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }
        socket.getOutputStream().write("上传成功".getBytes());
        fos.close();
        socket.close();
        serverSocket.close();
    }
}

文件上传案例优化

服务器点优化就够了

package com.monfolld.net.FileUploadp;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;


public class TCPServerp {
    public static void main(String[] args)throws IOException {
        ServerSocket serverSocket=new ServerSocket(8888);

        /*让服务器一直处于监听状态(死循环accept方法)
        * 有一个客户端上传文件,就保存一个文件*/
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    //完成文件的上传
                    while (true) {
                        Socket socket = serverSocket.accept();
                        /*使用多线程计数,提高程序的效率
                         * 有一个客户端就上传文件,就开启一个线程,完成文件的上传*/
                        InputStream is = socket.getInputStream();
                        File file = new File("d:\\upload");
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        /*自定义一个文件的命名跪着:防止同名的文件被覆盖
                         * 规则:域名+毫秒值+随机数*/
                        String filenmae = "itcast" + System.currentTimeMillis() + new Random().nextInt(99999) + ".jpg";
                        FileOutputStream fos = new FileOutputStream(file + "\\" + filenmae);


                        int len = 0;
                        byte[] bytes = new byte[1024];
                        while ((len = is.read(bytes)) != -1) {
                            fos.write(bytes, 0, len);
                        }
                        socket.getOutputStream().write("上传成功".getBytes());
                        fos.close();
                        socket.close();

            }
        }catch (IOException e){
                    System.out.println(e);
                 }
                }
            } ).start();
        }
        //服务器就不用关闭
        //serverSocket.close();
    }

B\S服务器

网站浏览服务器

 服务器端

package com.monfolld.net.BSTCP;

import com.sun.org.apache.bcel.internal.generic.NEW;

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

public class TCPServer {
    public static void main(String[] args) throws IOException {
        //创建一个服务器ServerSocket,和系统要指定的端口号
        ServerSocket server = new ServerSocket(8080);

        /*浏览器解析服务器回写html页面,页面中如果有图片,那么浏览器就会单独的开启一个线程,读取服务器的图片
        * 我们就让服务器一直处于监听状态,客户端请求一次服务器就会写一次*/
        while (true){
            //使用accept方法获取到请求的客户端对象(浏览器)
            Socket socket = server.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //使用Socket对象中的getInputStream,获取到网络字节输入流InputStream对象
                        InputStream is = socket.getInputStream();
                        //使用网络字节输入流InputStream对象中的方法read读取客户端的请求信息
        /*byte[] bytes=new byte[1024];
        int len=0;
        while ((len=is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }*/
                        //把is网络字节输入流对象,转换为字符缓冲输入流
                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
                        //把客户端请求信息的第一行读取出来 GET /11_Net/web/index.html
                        String line = br.readLine();
                        //吧读取的信息进行切割,只要中间部分
                        String[] arr = line.split(" ");
                        String htmlpath = arr[1].substring(1);
                        //创建一个本地字节输入流,构造方法中绑定要读取的html路径
                        FileInputStream fis = new FileInputStream(htmlpath);
                        //使用Socket中的getOutputStream获取网络字节输出流OutputStream对象
                        OutputStream os = socket.getOutputStream();

                        //写入Http协议响应头,固定写法
                        os.write("HTTP/1.1 200 OK\r\n".getBytes());
                        os.write("Content-Type:text/html\r\n".getBytes());
                        //必须要写入空行,否则浏览器不解析
                        os.write("\r\n".getBytes());

                        //一读一写复制文件,吧服务器读取的html文件写回客户端
                        byte[] bytes = new byte[1024];
                        int len = 0;
                        while ((len = fis.read(bytes)) != -1) {
                            os.write(bytes, 0, len);
                        }
                        fis.close();
                        socket.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }).start();

        }
        //server.close();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值