Java API —— 网络编程

1、网络编程概述

1)网络编程概述

· 计算机网络

是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

· 网络编程

就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

2)网络模型

· 计算机网络之间以何种规则进行通信,就是网络模型研究问题。

· 网络模型一般是指

· OSI(Open System Interconnection开放系统互连)参考模型

· TCP/IP参考模型

3)网络参考模型图

2、网络编程三要素

1)IP地址:InetAddress

    网络中设备的标识,不易记忆,可用主机名

2)端口号

    用于标识进程的逻辑地址,不同进程的标识

3)传输协议

  通讯的规则,常见协议:TCP,UDP

    UDP:将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快

    TCP:建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低

4)InetAddress类的使用

· 获取任意主机:public static InetAddress getByName(String host):根据主机名或者IP地址的字符串表示得到IP地址对象

   · 主机名:getHostName

    · 主机IP地址:getHostAddress    

package netcoding;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
 * Created by gao on 16-1-14.
 */
/*
 * 如果一个类没有构造方法:
 * A:成员全部是静态的(Math,Arrays,Collections)
 * B:单例设计模式(Runtime)
 * C:类中有静态方法返回该类的对象(InetAddress)
 *         class Demo {
 *             private Demo(){}
 *
 *             public static Demo getXxx() {
 *                 return new Demo();
 *             }
 *         }
 *
 * 看InetAddress的成员方法:
 * public static InetAddress getByName(String host):根据主机名或者IP地址的字符串表示得到IP地址对象
 */
public class NetDemo01 {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress address = InetAddress.getByName("shlgao84");
        String name = address.getHostName();
        String ip = address.getHostAddress();
        System.out.println(name + "---" + ip);
    }
}

5)端口号

· 物理端口 网卡口

· 逻辑端口 我们指的就是逻辑端口

    A:每个网络程序都会至少有一个逻辑端口

    B:用于标识进程的逻辑地址,不同进程的标识

    C:有效端口:0~65535,其中0~1024系统使用或保留端口。

3、Socket

1)Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

2)Socket原理机制:通信的两端都有Socket。网络通信其实就是Socket间的通信。数据在两个Socket间通过IO传输。

4、UDP传输

· DatagramSocket与DatagramPacket

· 建立发送端,接收端。

· 建立数据包。

· 调用Socket的发送接收方法。

· 关闭Socket。

· 发送端与接收端是两个独立的运行程序。

1)UDP传输-发送端思路

A:建立udp的socket服务

B:将要发送的数据封装成数据包

C:通过udp的socket服务,将数据包发送出

D:关闭资源

2)UDP传输-接收端思路

A:建立udp的socket服务.

B:通过receive方法接收数据

C:将收到的数据存储到数据包对象中

D:通过数据包对象的功能来完成对接收到数据进行解析.

E:可以对资源进行关闭

例子1:发送端

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
public class SendDemo01 {
    public static void main(String[] args) throws IOException {
        // 创建发送端Socket对象
        // DatagramSocket()
        DatagramSocket ds = new DatagramSocket();
        // 创建数据,并把数据打包
        // DatagramPacket(byte[] buf, int length, InetAddress address, int port)
        // 创建数据
        byte[] bys = "hello,udp,我来了".getBytes();
        // 长度
        int len = bys.length;
        // IP地址对象
        InetAddress address = InetAddress.getByName("10.130.26.23");
        // 端口
        int port = 10086;
        DatagramPacket dp = new DatagramPacket(bys,len,address,port);
        // 调用Socket对象的发送方法发送数据包
        // public void send(DatagramPacket p)
        ds.send(dp);
        // 释放资源
        ds.close();
    }
}

接收端:

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
public class ReceiveDemo01 {
    public static void main(String[] args) throws IOException {
        // 创建接收端Socket对象
        // DatagramSocket(int port)
        DatagramSocket ds = new DatagramSocket(10086);
        // 创建一个数据包(接收容器)
        // DatagramPacket(byte[] buf, int length)
        byte[] bys = new byte[1024];
        int length = bys.length;
        DatagramPacket dp = new DatagramPacket(bys, length);
        // 调用Socket对象的接收方法接收数据
        ds.receive(dp);// 阻塞式
        // 解析数据包,并显示在控制台
        // 获取对方的ip
        // public InetAddress getAddress()
        InetAddress address = dp.getAddress();
        String ip = address.getHostAddress();
        // public byte[] getData():获取数据缓冲区
        // public int getLength():获取数据的实际长度
        byte[] bys2 = dp.getData();
        int len = dp.getLength();
        String s = new String(bys2, 0, len);
        System.out.println(ip + "传递的数据是:" + s);
        // 释放资源
        ds.close();
    }
}

例子2:发送端(优化代码)

package netcoding;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
/*
* 数据来自于键盘录入
* 键盘录入数据要自己控制录入结束。
*/
public class SendDemo02 {
    public static void main(String[] args) throws IOException {
        // 创建发送端的Socket对象
        DatagramSocket ds = new DatagramSocket();
        // 封装键盘录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = br.readLine())!= null) {
            if ("886".equals(line)){
                break;
            }
            // 创建数据并打包
            byte[] bys = line.getBytes();
            DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("10.130.26.23"), 12345);
            //DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("10.130.26.255"), 10086);
            // 发送数据
            ds.send(dp);
        }
        // 释放资源
        ds.close();
    }
}

接收端:

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
 * Created by gao on 16-1-18.
 */
/*
 * 多次启动接收端:
 * java.net.BindException: Address already in use: Cannot bind
 * 端口被占用。
 */
public class ReceiveDemo02 {
    public static void main(String[] args) throws IOException {
        // 创建接收端的Socket对象
        DatagramSocket ds = new DatagramSocket(12345);
        while (true) {
            // 创建一个包裹
            byte[] bys = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);
            // 接收数据
            ds.receive(dp);
            // 解析数据
            String ip = dp.getAddress().getHostAddress();
            String s = new String(dp.getData(), 0, dp.getLength());
            System.out.println("from:" + ip + " data is:" + s);
        }
        // 释放资源
        // 接收端应该一直开着等待接收数据,是不需要关闭
        // ds.close();
    }
}

例子3:(多线程实现聊天室程序)

主函数:

package netcoding;
import java.io.IOException;
import java.net.DatagramSocket;
/**
 * Created by gao on 16-1-18.
 */
public class ChatRoom {
    public static void main(String[] args) throws IOException {
        DatagramSocket dsSend = new DatagramSocket();
        DatagramSocket dsReceive = new DatagramSocket(12306);
        SendThread st = new SendThread(dsSend);
        ReceiveThread rt = new ReceiveThread(dsReceive);
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(rt);
        t1.start();
        t2.start();
    }
}

发送线程:

package netcoding;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
public class SendThread implements Runnable {
    private DatagramSocket ds;
    public SendThread(DatagramSocket ds) {
        this.ds = ds;
    }
    @Override
    public void run() {
        try {
            // 封装键盘录入数据
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    System.in));
            String line = null;
            while ((line = br.readLine()) != null) {
                if ("886".equals(line)) {
                    break;
                }
                // 创建数据并打包
                byte[] bys = line.getBytes();
                // DatagramPacket dp = new DatagramPacket(bys, bys.length,
                // InetAddress.getByName("192.168.12.92"), 12345);
                DatagramPacket dp = new DatagramPacket(bys, bys.length,
                        InetAddress.getByName("10.130.26.23"), 12306);
                // 发送数据
                ds.send(dp);
            }
            // 释放资源
            ds.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

接收线程:

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
 * Created by gao on 16-1-18.
 */
public class ReceiveThread implements Runnable{
    private DatagramSocket ds;
    public ReceiveThread(DatagramSocket ds) {
        this.ds = ds;
    }
    @Override
    public void run() {
        try {
            while (true) {
                // 创建一个包裹
                byte[] bys = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bys, bys.length);
                // 接收数据
                ds.receive(dp);
                // 解析数据
                String ip = dp.getAddress().getHostAddress();
                String s = new String(dp.getData(), 0, dp.getLength());
                System.out.println("from " + ip + " data is : " + s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5、TCP传输

· Socket和ServerSocket

· 建立客户端和服务器端

· 建立连接后,通过Socket中的IO流进行数据的传输

· 关闭socket

· 同样,客户端与服务器端是两个独立的应用程序。

    1)TCP传输-客户端思路

  A:建立客户端的Socket服务,并明确要连接的服务器。
  B:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
  C:通过Socket对象的方法,可以获取这两个流
  D:通过流的对象可以对数据进行传输
  E:如果传输数据完毕,关闭资源

    2)TCP传输-服务器端思路

A:建立服务器端的socket服务,需要一个端口

B:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信

C:通过客户端的获取流对象的方法,读取数据或者写入数据

D:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的

例子1:

服务器:

package netcoding;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
/*
 * TCP协议接收数据:
 * A:创建接收端的Socket对象
 * B:监听客户端连接。返回一个对应的Socket对象
 * C:获取输入流,读取数据显示在控制台
 * D:释放资源
 */
public class ServerDemo01 {
    public static void main(String[] args) throws IOException {
        // 创建接收端的Socket对象
        // ServerSocket(int port)
        ServerSocket ss = new ServerSocket(12306);
        // 监听客户端连接。返回一个对应的Socket对象
        // public Socket accept()
        Socket s = ss.accept();  // 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
        // 获取输入流,读取数据显示在控制台
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);  // 阻塞式方法
        String str = new String(bys, 0, len);
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "---" + str);
        // 释放资源
        s.close();
        // ss.close(); //这个不应该关闭
    }
}

客户端:

package netcoding;
import com.sun.org.apache.xml.internal.serializer.OutputPropertyUtils;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
/*
 * TCP协议发送数据:
 * A:创建发送端的Socket对象
 *         这一步如果成功,就说明连接已经建立成功了。
 * B:获取输出流,写数据
 * C:释放资源
 *
 * 连接被拒绝。TCP协议一定要先看服务器。
 * java.net.ConnectException: Connection refused: connect
 */
public class ClientDemo01 {
    public static void main(String[] args) throws IOException{
        // 创建发送端的Socket对象
        // Socket(InetAddress address, int port)
        // Socket(String host, int port)
        // Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
        Socket s = new Socket("10.130.26.23",12306);
        // 获取输出流,写数据
        // public OutputStream getOutputStream()
        OutputStream os = s.getOutputStream();
        os.write("hello tcp.".getBytes());
        // 释放资源
        s.close();
    }
}

例子2:服务器给客户端反馈

服务器

package netcoding;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
public class ServerDemo02 {
    public static void main(String[] args) throws IOException {
        // 创建服务器Socket对象
        ServerSocket ss = new ServerSocket(12306);
        // 监听客户端的连接
        Socket s = ss.accept(); // 阻塞
        // 获取输入流
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys); // 阻塞
        String server = new String(bys, 0, len);
        System.out.println("server:" + server);
        // 获取输出流
        OutputStream os = s.getOutputStream();
        os.write("数据已经收到".getBytes());
        // 释放资源
        s.close();
        // ss.close();
    }
}

客户端

package netcoding;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
public class ClientDemo02 {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket s = new Socket("10.130.26.23", 12306);
        // 获取输出流
        OutputStream os = s.getOutputStream();
        os.write("ClientDemo02".getBytes());
        // 获取输入流
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys); // 阻塞
        String client = new String(bys, 0, len);
        System.out.println("client:" + client);
        // 释放资源
        s.close();
    }
}

例子3:客户端键盘录入,服务器输出到控制台

服务器

package cn.itcast_08;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建服务器Socket对象
        ServerSocket ss = new ServerSocket(22222);
        // 监听客户端连接
        Socket s = ss.accept();
        // 包装通道内容的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        // br.close();
        s.close();
        // ss.close();
    }
}

客户端

package cn.itcast_08;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 客户端键盘录入,服务器输出到控制台
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket s = new Socket("192.168.12.92", 22222);
        // 键盘录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 把通道内的流给包装一下
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            // 键盘录入数据要自定义结束标记
            if ("886".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 释放资源
        // bw.close();
        // br.close();
        s.close();
    }
}

例子4:客户端键盘录入,服务器输出文本文件

服务器端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建服务器Socket对象
        ServerSocket ss = new ServerSocket(23456);
        // 监听客户端连接
        Socket s = ss.accept();
        // 封装通道内的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 封装文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        // br.close();
        s.close();
        // ss.close();
    }
}

客户端:

package cn.itcast_09;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 客户端键盘录入,服务器输出文本文件
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket s = new Socket("192.168.12.92", 23456);
        // 封装键盘录入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 封装通道内的数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            if ("over".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // bw.close();
        // br.close();
        s.close();
    }
}

例子5:客户端文本文件,服务器输出到控制台

服务器端:

package cn.itcast_10;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建服务器Socket对象
        ServerSocket ss = new ServerSocket(34567);
        // 监听客户端连接
        Socket s = ss.accept();
        // 封装通道内的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        s.close();
    }
}

客户端:

package cn.itcast_10;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 客户端文本文件,服务器输出到控制台
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建Socket对象
        Socket s = new Socket("192.168.12.92", 34567);
        // 封装文本文件
        BufferedReader br = new BufferedReader(new FileReader(
                "InetAddressDemo.java"));
        // 封装通道内的流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        s.close();
    }
}

例子6:客户端文本文件,服务器输出文本文件

服务器端:

package cn.itcast_12;
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.ServerSocket;
import java.net.Socket;
public class UploadServer {
    public static void main(String[] args) throws IOException {
        // 创建服务器端的Socket对象
        ServerSocket ss = new ServerSocket(11111);
        // 监听客户端连接
        Socket s = ss.accept();// 阻塞
        // 封装通道内的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 封装文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
        String line = null;
        while ((line = br.readLine()) != null) { // 阻塞
        // if("over".equals(line)){
        // break;
        // }
            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();
    }
}

客户端:

package cn.itcast_12;
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;
/*
 * 按照我们正常的思路加入反馈信息,结果却没反应。为什么呢?
 * 读取文本文件是可以以null作为结束信息的,但是呢,通道内是不能这样结束信息的。
 * 所以,服务器根本就不知道你结束了。而你还想服务器给你反馈。所以,就相互等待了。
 *
 * 如何解决呢?
 * A:在多写一条数据,告诉服务器,读取到这条数据说明我就结束,你也结束吧。
 *         这样做可以解决问题,但是不好。
 * B:Socket对象提供了一种解决方案
 *         public void shutdownOutput()
 */
public class UploadClient {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket s = new Socket("192.168.12.92", 11111);
        // 封装文本文件
        BufferedReader br = new BufferedReader(new FileReader(
                "InetAddressDemo.java"));
        // 封装通道内流
        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();

        //Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了
        s.shutdownOutput();
        // 接收反馈
        BufferedReader brClient = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String client = brClient.readLine(); // 阻塞
        System.out.println(client);
        // 释放资源
        br.close();
        s.close();
    }
}

例子7:上传图片案例

服务器端:

package cn.itcast_13;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
    public static void main(String[] args) throws IOException {
        // 创建服务器Socket对象
        ServerSocket ss = new ServerSocket(19191);
        // 监听客户端连接
        Socket s = ss.accept();
        // 封装通道内流
        BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
        // 封装图片文件
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("mn.jpg"));
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }
        // 给一个反馈
        OutputStream os = s.getOutputStream();
        os.write("图片上传成功".getBytes());
        bos.close();
        s.close();
    }
}

客户端:

package cn.itcast_13;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class UploadClient {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket s = new Socket("192.168.12.92", 19191);
        // 封装图片文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "林青霞.jpg"));
        // 封装通道内的流
        BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }

        s.shutdownOutput();
        // 读取反馈
        InputStream is = s.getInputStream();
        byte[] bys2 = new byte[1024];
        int len2 = is.read(bys2);
        String client = new String(bys2, 0, len2);
        System.out.println(client);
        // 释放资源
        bis.close();
        s.close();
    }
}

例子8:服务器的代码用线程进行封装,这样可以模拟一个同时接收多人上传文件的服务器。(用循环也可以但是效率低,是单线程的程序)

服务器线程:

package cn.itcast_15;
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();
        }
    }
}

服务器端:

package cn.itcast_15;
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(11111);
        while (true) {
            Socket s = ss.accept();
            new Thread(new UserThread(s)).start();
        }
    }
}

客户端:

package cn.itcast_15;
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.12.92", 11111);
        // 封装文本文件
        // BufferedReader br = new BufferedReader(new FileReader(
        // "InetAddressDemo.java"));
        BufferedReader br = new BufferedReader(new FileReader(
                "ReceiveDemo.java"));
        // 封装通道内流
        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();
    }
}
时间: 2024-11-05 20:34:01

Java API —— 网络编程的相关文章

JAVA的网络编程【转】

网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编程是比较复杂的系统工程,需要了解很多和网络相关的基础知识,其实这些都不是很必需的.首先来问一个问题:你 会打手机吗?很多人可能说肯定会啊,不就是按按电话号码,拨打电话嘛,很简单的事情啊!其实初学者如果入门网络编程的话也可以做到这么简单! 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作

JAVA的网络编程

网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编程是比较复杂的系统工程,需要了解很多和网络相关的基础知识,其实这些都不是很必需的.首先来问一个问题:你 会打手机吗?很多人可能说肯定会啊,不就是按按电话号码,拨打电话嘛,很简单的事情啊!其实初学者如果入门网络编程的话也可以做到这么简单! 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.

Java NIO 网络编程基础

Java NIO提供了一套网络api,可以用来处理连接数很多的情况.他的基本思想就是用一个线程来处理多个channel. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899

Java - TCP网络编程

Java - TCP网络编程 Server 逻辑思路: 创建ServerSocket(port),然后服务器的socket就启动了 循环中调用accept(),此方法会堵塞程序,直到发现用户请求,返回用户的socket 利用多线程对用户socket进行IO操作 注意:对Scoket/File进行创建.关闭,都需要放try catch中,检测 IOException,所以将网络IO部分整体放入try catch中即可. 1. 字符串操作 输出:PrintWriter out=new PrintWr

java io 网络编程 高性能NIO

很久没写了,一是觉得这后台不怎么方便,二是 写的时候突然觉得没兴趣了. 还好,今天突然想记一下,那就随便写吧.  1.一开始还是放几个连接.  什么是 同步,异步,阻塞,非阻塞 : http://blog.csdn.net/historyasamirror/article/details/5778378        从Jetty.Tomcat和Mina中提炼NIO构架网络服务器的经典模式:http://blog.csdn.net/cutesource/article/details/61920

Java Socket 网络编程心跳设计概念

Java Socket 网络编程心跳设计概念 1.一般是用来判断对方(设备,进程或其它网元)是否正常动行,一 般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于检测TCP的异常断开.一般是用来判断对方(设备,进程或其它 网元)是否正常动行,一般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于检测TCP的异常断开.基本原因是服务 器端不能有效的判断客户端是否在线也就是说,服务器无法区分客户端是长时间在空闲,还是已经掉线的情况.

java 中网络编程

网络编程 IP地址: 主机在网络中的逻辑地址 Port: 标定主机中的进程 一个进程绑定一个端口 协议: 网络双方约定的通信标准 应用 表示 应用 HTTP FTP TELNET 会话 传输 传输 网络 网络 寻址和路由 数据链路 网络接口 TCP/IP 物理 传输 TCP 传输控制协议 连接 安全可靠 UDP 用户数据报协议 无连接 不可靠 Socket 套接字 java 中网络编程

Java Socket网络编程Server端详解

Socket通信:分为客户端和服务端的socket代码. Java SDK提供一些相对简单的Api来完成.对于Java而言.这些Api存在与java.net 这个包里面.因此只要导入这个包就可以开始网络编程了. 网络编程的基本模型就是客户机到服务器模型.简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置.并去建立两者之间的联系,然后完成数据的通讯就可以了.这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端.了解这个简单的模型,就可以

Java Socket网络编程的经典例子(转)

事实上网络编程简单的理解就是两台计算机相互通讯数据而已,对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了,Java SDK提供一些相对简单的Api来完成这些工作.Socket就是其中之一,对于Java而言,这些Api存在与java.net 这个包里面,因此只要导入这个包就可以准备网络编程了. 网络编程的基本模型就是客户机到服务器模型,简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置.并去建立两者之间的联系,然后完成