Java基础--网络编程

1.网络基础概念​
什么是计算机网络:​
把分布在不同地理区域的计算机与专门的外部设备用通讯线路互连成一个规模大,功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬盘,软件,数据信息等资源。​
网络通信协议及接口​
网络通信协议:计算机网络中实现通信必须有一些约定即通信协议,对速率,传输代码,代码结构,传输控制步骤,出错控制等制定标准。​
网络通信接口:为了使两个结点之间能进行对话,必须在它们之间建立通信工具(即接口),使彼此之间能够进行信息交换,接口包括两部分:硬件装置:实现结点之间的信息传送,软件装置:规定双方进行通信的约定协议。​
通信协议分层的思想:​
由于结点之间联系很复杂,在制定协议时,把复杂成分分解成一些简单的成分,在将它们复合起来。最常用的复合方式就是层次方式,即同层间可以通信,上一层可以调用下一层,而与在下一层不发生关系,各层互不影响,利于系统的开发和扩展。​
通信协议的分层规定:把用户应用程序作为最高层,把物理通信线路最为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准。​
参考模型:​
OSI参考模型:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层​
TCP/IP参考模型:应用层                          传输层,网络层,物理+数据链路层​
数据封装,数据拆封​
IP协议​
IP(Internet  Protocol)协议是网际层的主要协议,支持网间互连的数据报通信、提供只要功能有:无连接数据报传送,数据报路由选择和差错控制​
贡献:每个机器都有自己独一无二的IP地址​
IP地址本身占4个字节,每一个地址占一个字节,每一位最多表示255,其中有一位(A类网),二位(B类网),三位(C类网),所谓一位二位就像是移动电话号码的前3位,如126为IBM所有,126.xxx.xxx.xxx的所有地址均归IBM所有​。
子网掩码(subnet mask)是每个使用互联网的人必须要掌握的基础知识,只有掌握它,才能够真正理解TCP/IP协议的设置。子网掩码——屏蔽一个IP地址的网络部分的“全1”比特模式。对于A类地址来说,默认的子网掩码是255.0.0.0;对于B类地址来说默认的子网掩码是255.255.0.0;对于C类地址来说默认的子网掩码是255.255.255.0。利用子网掩码可以把大的网络划分成子网,即VLSM(可变长子网掩码),也可以把小的网络归并成大的网络即超网。​
网关(Gateway)又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关既可以用于广域网互连,也可以用于局域网互连。网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同层--应用层。​
TCP协议​
TCP(transmission control protocol)是专门设计用于在不可靠的因特网上提供可靠的,端到端的字节流通信的协议。它是一种面对连接的协议,TCP连接是字节流而非报文流。(报文(message)是网络中交换与传输的数据单元,即站点一次性要发送的数据块。报文包含了将要发送的完整的数据信息,其长短很不一致,长度不限且可变。)​
UDP(user data protocol)​
UDP向应用程序提供了一种发送封装的原始IP数据报的方法,并且发送时无需建立连接。是一种不可靠的连接。​
2.Socket​​
两个java应用程序可通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个socket。​
socket通常用来实现client-server连接,java.net包中定义的两个类socket和serversocket,分别用来实现双向连接的client和server端,建立连接时所需的寻址信息为远程计算机的IP地址和端口号(port number 2个字节,TCP端口和UDP端口各65536个,用1024以上的,1024以下的系统调用)​​
public class TestServer {
    public static void main(String args[]) throws Exception {
        ServerSocket ss = new ServerSocket(6666);
        while (true) {
            Socket s = ss.accept();
            DataInputStream dis = new DataInputStream(s.getInputStream());
            System.out.println(dis.readUTF());//阻塞式的读方法
            dis.close();
            s.close();
        }
    }
}
public class TestClient {
    public static void main(String args[]) throws Exception {
        Socket s = new Socket("127.0.0.1", 6666);
        OutputStream os = s.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("hello server!");
        dos.flush();
        dos.close();
        s.close();
    }
}
运行了Server后在运行Client会打印出hello serve!​

该程序中所用的ReadUTF方法是阻塞式的,在其运行时别的Client不能连接到Server上,例如,让Client睡眠30秒在写入hello Server,与此同时在运行一个Client,该Client就不能连接到Server上。


例子程序:​
public class TCPServer {
    public static void main(String args[]) {
        try {
            ServerSocket s = new ServerSocket(8888);
            while (true) {
                Socket s1 = s.accept();
                OutputStream os = s1.getOutputStream();
                DataOutputStream dos = new DataOutputStream(os);
                dos.writeUTF("Hello," + s1.getInetAddress() +
                        "port#" + s1.getPort() + " bye-bye!");
                dos.close();
                s1.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("程序运行出错:" + e);
        }
    }
}
public class TCPClient {
    public static void main(String args[]) {
        try {
            Socket s1 = new Socket("127.0.0.1", 8888);
            InputStream is = s1.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            System.out.println(dis.readUTF());
            dis.close();
            s1.close();
        } catch (ConnectException connExc) {
            connExc.printStackTrace();
            System.err.println("服务器连接失败!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


结果是:Hello,/127.0.0.1port#63210 bye-bye!​​
双机之间单次通信:
public class TestScoketServer {
    public static void main(String[] args) {
        InputStream in = null;
        OutputStream out = null;
        try {
            ServerSocket ss = new ServerSocket(5888);
            Socket socket = ss.accept();
            in = socket.getInputStream();
            out = socket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(out);
            DataInputStream dis = new DataInputStream(in);
            String s = null;
            if ((s = dis.readUTF()) != null) {
                System.out.println(s);
                System.out.println("from: " + socket.getInetAddress());
                System.out.println("Port: " + socket.getPort());
            }
            dos.writeUTF("hi,hello");
            dis.close();
            dos.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class TestSocketClient {
    public static void main(String[] args) {
        InputStream is = null;
        OutputStream os = null;
        try {
            Socket socket = new Socket("localhost", 5888);
            is = socket.getInputStream();
            os = socket.getOutputStream();
            DataInputStream dis = new DataInputStream(is);
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF("hey");
            String s = null;
            if ((s = dis.readUTF()) != null) ;
            System.out.println(s);
            dos.close();
            dis.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

结果:运行server后,再运行Client,servser是先读后写,Client是先写后读,client->hey,servser读出from:/127.0.0.1  Port:1969   然后server->hi,hello​
双机之间的多次通信实现:
public class ChatServer {
    public static void main(String args[]) {
        try {
            ServerSocket server = null;
            try {
                server = new ServerSocket(8888);
            } catch (Exception e) {
                System.out.println("can not listen to:" + e);
            }
            Socket socket = null;
            try {
                socket = server.accept();
            } catch (Exception e) {
                System.out.println("Error." + e);
            }
            String line;
            BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter os = new PrintWriter(socket.getOutputStream());
            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Client:" + is.readLine());
            line = sin.readLine();
            while (!line.equals("bye")) {
                os.println(line);
                os.flush();
                System.out.println("Server:" + line);
                System.out.println("Client:" + is.readLine());
                line = sin.readLine();
            } // 继续循环
            os.close(); // 关闭Socket输出流
            is.close(); // 关闭Socket输入流
            socket.close(); // 关闭Socket
            server.close(); // 关闭ServerSocket
        } catch (Exception e) {
            System.out.println("Error:" + e);
        }
    }
}
public class ChatClient {
    public static void main(String args[]) {
        try {
            Socket socket = new Socket("127.0.0.1", 8888);   // 向本机的4700端口发出客户请求
            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));   // 由系统标准输入设备构造BufferedReader对象
            PrintWriter os = new PrintWriter(socket.getOutputStream());   // 由Socket对象得到输出流,并构造PrintWriter对象
            BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));   // 由Socket对象得到输入流,并构造相应的BufferedReader对象
            String readline;
            readline = sin.readLine(); // 从系统标准输入读入一字符串
            while (!readline.equals("bye")) {    // 若从标准输入读入的字符串为 "bye"则停止循环
                os.println(readline);    // 将从系统标准输入读入的字符串输出到Server
                os.flush();    // 刷新输出流,使Server马上收到该字符串
                System.out.println("Client:" + readline);    // 在系统标准输出上打印读入的字符串
                System.out.println("Server:" + is.readLine());    // 从Server读入一字符串,并打印到标准输出上
                readline = sin.readLine(); // 从系统标准输入读入一字符串
            } // 继续循环
            os.close(); // 关闭Socket输出流
            is.close(); // 关闭Socket输入流
            socket.close(); // 关闭Socket
        } catch (Exception e) {
            System.out.println("Error" + e);
        }
    }
}

这里只能是在客户端先行输入之后,才能在服务器端的到响应,即是先运行server在运行client,最后在client中输入,server得到显示,再在server中输入同样client可以显示,如是继续。
3.UDP的Socket​
如范例:​
public class TestUDPServer1 {
    public static void main(String args[]) throws Exception {
        byte buf[] = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);//包裹,发来的数据存在DatagramPacket,实际是数组中
        DatagramSocket ds = new DatagramSocket(5678);
        while (true) {
            ds.receive(dp);//接收数据,相当于ReadUTF,是阻塞式的
            System.out.println(new String(buf, 0, dp.getLength()));//String的一个构造方法
        }
    }
}
public class TestUDPClient1 {
    public static void main(String args[]) throws Exception {
        byte[] buf = (new String("Hello")).getBytes();//返回byte类型的数组
        DatagramPacket dp = new DatagramPacket(buf, buf.length, new InetSocketAddress("127.0.0.1", 5678));//InetSocketAddress继承自SocketAddress
        DatagramSocket ds = new DatagramSocket(9999);
        ds.send(dp);
        ds.close();
    }
}

结果是:hello​
传送一个lang类型的数的程序:​
public class TestUDPServer {
    public static void main(String args[]) throws Exception {
        byte buf[] = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        DatagramSocket ds = new DatagramSocket(5678);
        while (true) {
            ds.receive(dp);
            ByteArrayInputStream bais = new ByteArrayInputStream(buf);
            DataInputStream dis = new DataInputStream(bais);
            System.out.println(dis.readLong());
        }
    }
}
public class TestUDPClient {
    public static void main(String args[]) throws Exception {
        long n = 10000L;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeLong(n);
        byte[] buf = baos.toByteArray();
        System.out.println(buf.length);
        DatagramPacket dp = new DatagramPacket(buf, buf.length, new InetSocketAddress("127.0.0.1", 5678));
        DatagramSocket ds = new DatagramSocket(9999);
        ds.send(dp);
        ds.close();
    }
}
结果:10000
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值