• Java网络编程学习


         服务器是指提供信息的计算机或程序,客户机是指请求信息的计算机或程序,而网络用于连接服务器与客户机,实现两者相互通信。但有时在某个网络中很难将服务器与客户机区分开。我们通常所说的“局域网”(Local Area Network,LAN),就是一群通过一定形式连接起来的计算机。它可以由两台计算机组成,也可以由同一区域内的上千台计算机组成。由LAN延伸到更大的范围,这样的网络称为“广域网”(Wide Area Network,WAN)。我们熟悉的因特网(Internet),则是由无数的LAN和WAN组成。

         一般而言,一台计算机只有单一的连到网络的“物理连接”(Physical Connection),所有的数据都通过此连接对内、对外送达特定的计算机。这就是端口。网络程序设计中的端口(port)并非真实的物理存在,而是一个假想的连接装置。端口被规定为一个在0~65535之间的整数。HTTP服务一般使用80端口,FTP服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务,那么客户机通过不同的端口来确定连接到服务器的哪项服务上,如下图所示。

         网络程序中套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插插头的设备“插座”,用于连接电器与电线,如下图所示。Java将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。

     

    TCP程序设计:

    步骤:

    1、  服务器创建ServerSocket,调用accept()方法等待客户机请求。

    2、  客户端创建Socket,请求服务器。

    3、  服务器接收请求,accept()方法返回一个Socket,从而建立连接。

    InetAddress类——IP相关

    ServerSocket类——服务器套接字

    主要功能是等待来自网络上的“请求”,它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是50。

    构造函数:

    ServerSocket() throws IOException

    ServerSocket(int port) throws IOException

    ServerSocket(int port, int backlog) throws IOException

    ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException

    java socket中有两个流,
    一个是输入流getInputStream,用于读取socket发送过来的数据,就是接收消息用的。
    另一个是输出流getOutputStream,用于向socket端发送数据,就是发送消息用的。

    代码示例:

    TCPServer.java

    /*
     * TCPServer
     * @author ChenMing
     * @version 2016-7-10
     */
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class TCPServer {
        public static void main(String[] args) {
            try{
                /*******************************监听并连接***********************************/
                ServerSocket serverSocket = null ; 
                try{
                    serverSocket = new ServerSocket(4000) ; //创建一个端口监听
                }catch(Exception e){
                    e.printStackTrace();
                }
                Socket socket = null ; 
                try{
                    System.out.println("服务器开启!");
                    socket = serverSocket.accept() ; //一直阻塞,直到接收到请求,返回一个Socket
                }catch(Exception e){
                    e.printStackTrace();
                }
                
                /*******************************接收连接***********************************/
                //由socket对象得到输入流,并构造相应的BufferedReader
                BufferedReader read = new BufferedReader(new InputStreamReader(socket.getInputStream())) ;
                try{
                    while(true){
                        System.out.println("服务器收到:"+read.readLine());
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
                /*******************************关闭连接***********************************/
                try{
                    if (read!=null)
                        read.close();
                    if (socket!=null)
                        socket.close();
                    if (serverSocket!=null)
                        serverSocket.close();
                    System.out.println("服务器关闭!");
                }catch(Exception e){
                    e.printStackTrace();
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
    }

    TCPClient.java

    /*
     * TCPClient
     * @author ChenMing
     * @version 2016-7-10
     */
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    public class TCPClient {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            try{
                /*******************************请求连接***********************************/
                //向本机的5000端口发出客户请求
                Socket socket = null ;
                socket = new Socket("127.0.0.1", 4000)  ;
                //由系统标准输入设备构造BufferReader对象
                System.out.println("客户端连接成功!");
                /*******************************传输数据***********************************/
                BufferedReader in = null ; 
                in = new BufferedReader(new InputStreamReader(System.in)) ; 
                //由Socket对象得到输出流,并构造PrintWriter对象
                PrintWriter writer = null ; 
                writer = new PrintWriter(socket.getOutputStream()) ; 
                try{
                    while(true){
                        writer.println(in.readLine()); //将从系统标准输入读入的字符串输出到Server
                        writer.flush(); //刷新输出流,使Server马上收到该字符串
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
                /*******************************关闭连接***********************************/
                try{
                    if(in!=null)
                        in.close(); 
                    if(writer!=null)
                        writer.close();
                    if(socket!=null)
                        socket.close();  
                    System.out.println("客户端连接断开!");
                }catch(Exception e){
                    e.printStackTrace();
                }
                
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
    }

    UDP程序设计:

    基本模式如下:

    1、将数据打包,发送目的地

    2、接收别人发来的数据包,查看

    发送数据包——

    1、使用DatagramSocket()创建一个数据包套接字

    2、使用DatagramPackage(byte[] buf,int offset,int length,InetAddtress address,int port)创建要发送的数据包

    3、使用DatagramSocket类的send()方法发送数据包

    接收数据包——

    1、使用DatagramSocket(int port)创建一个数据包套接字

    2、使用DatagramPackage(byte[] buf, int length)创建要发送的数据包

    3、使用DatagramSocket类的receive()方法发送数据包

    几个类——

    java.net包的DatagramPacket类用来表示数据包。Datagram Packet类的构造函数有:

    DatagramPacket(byte[] buf , int length)

    DatagramPacket(byte[] buf , int length , InetAddress address , int port)

    第一种构造函数创建DatagramPacket对象,指定了数据包的内存空间和大小。第二种构造函数不仅指定了数据包的内存空间和大小,而且指定了数据包的目标地址和端口。在发送数据时,必须指定接收方的Socket地址和端口号,因此使用第二种构造函数可创建发送数据的DatagramPacket对象。

    java.net包中的DatagramSocket类用于表示发送和接收数据包的套接字。该类的构造函数有:

    DatagramSocket()

    DatagramSocket(int port )

    DatagramSocket(int port , InetAddress addr)

    第一种构造函数创建DatagramSocket对象,构造数据报套接字并将其绑定到本地主机上任何可用的端口。使用第二种构造函数创建DatagramSocket对象,创建数据报套接字并将其绑定到本地主机上的指定端口。第三种构造函数创建DatagramSocket对象,创建数据报套接字,将其绑定到指定的本地地址。第三种构造函数适用于有多块网卡和多个IP的情况。

    代码示例:

    UDPServer.java

    /*
     * UDPServer
     * @author ChenMing
     * @version 2016-7-11
     */
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    public class UDPServer {
        public static void main(String[] args) throws IOException {
            /**********************服务器接收客户端数据包************************/
            DatagramSocket server = null ; 
            server = new DatagramSocket(6000) ;
            byte[] recvBuf = new byte[100];
            DatagramPacket receive = new DatagramPacket(recvBuf , recvBuf.length); 
            server.receive(receive);
            //读包
            String recString = new String(receive.getData() , 0 , receive.getLength());
            System.out.println("从客户端收到:"+recString);
            
            /**********************服务器向客户端发送数据包*************************/
            int port = receive.getPort();
            InetAddress addr = receive.getAddress();
            String sendStr = "服务器刚才收到你的数据了!";
            byte[] sendBuf;
            sendBuf = sendStr.getBytes() ; 
            //打包
            DatagramPacket sendPacket = new DatagramPacket(sendBuf , sendBuf.length , addr , port );
            //发送
            server.send(sendPacket);
            if (server!=null)
                server.close();
        }
    }

    UDPClient.java

    /*
     * UDPClient
     * @author ChenMing
     * @version 2016-7-11
     */
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    public class UDPClient {
        public static void main(String[] args) throws IOException {
            /**********************客户端向服务器发送数据包*************************/
            DatagramSocket client = null ; 
            client = new DatagramSocket();
            String sendStr = "来自客户端的数据";
            byte[] sendBuf;
            sendBuf = sendStr.getBytes();
            InetAddress addr = InetAddress.getByName("127.0.0.1");
            int port = 6000;
            DatagramPacket send = new DatagramPacket(sendBuf ,sendBuf.length , addr , port);
            client.send(send);
            /**********************客户端接收服务器数据包************************/
            byte[] recvBuf = new byte[100];
            DatagramPacket receive = new DatagramPacket(recvBuf , recvBuf.length);
            client.receive(receive);
            String recvStr = new String(receive.getData() , 0 ,receive.getLength());
            System.out.println("收到来自服务器的数据:" + recvStr);
            if(client!=null)
                client.close();
        }
    }
  • 相关阅读:
    单例
    淘宝在数据处理领域的项目及开源产品介绍 | 岭南六少
    数据库垂直拆分,水平拆分利器,cobar升级版mycat
    基于Gtid的mysql主从复制 和 mysql-proxy 读写分离
    几行lua代码计算http包总长度_指甲锉_新浪博客
    使用Lua和OpenResty搭建验证码服务器
    测试比json更快更小的二进制数据传输格式Msgpack [pythono MessagePack 版本]
    使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
    nginx+lua+redis实现验证码防采集
    OpenResty(Nginx)+Lua+GraphicsMagick实现缩略图功能 | 琥珀志
  • 原文地址:https://www.cnblogs.com/xmu-chenming/p/5656919.html
Copyright © 2020-2023  润新知