java基础--socket

来源:互联网 发布:windows查看cpu 编辑:程序博客网 时间:2024/06/03 18:35

  java网络编程中一般用到的技术有:socket,IO,有时候也会用到图形界面。


socket,翻译为“套接字”,用于描述ip地址和端口。基于传输层协议的不同使用不同的Socket进行通信。
  UDP,面向无连接的传输协议,使用DatagramSocket,用来发送和接收数据报包的套接字。
  TCP,面向连接的传输协议,服务器端使用ServerSocket,客户端使用Socket,服务器端监听指定端口的连接并响应。

InetAddress 用来描述IP地址。无构造函数,常用的静态方法有:
  static InetAddress[] getAllByName(String host)  在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
  static InetAddress getByName(String host)   在给定主机名的情况下确定主机的 IP 地址。
  static InetAddress getLocalHost()   返回本地主机。


DatagramPacket类,用来表示数据报包,可将要发送的信息包装在此对象中,用来实现无连接包投递服务。其构造函数中带InetAddress和port参数的表示用来发送到指定主机上的数据报包,不带这两个参数的表示用来接收的数据报包。常用的方法有:
  getAddress()   返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
  getData()   返回数据缓冲区。
  getLength()   返回将要发送或接收到的数据的长度。
  setData(byte[] buf,int offset,int length)   为此包设置数据缓冲区。

DatagramSocket类,用来发送和接收数据报包的套接字,是包投递服务的发送或接收点。比较重要的是接收和发送方法:
  receive(DatagramPacket d)   接收数据报包
  send(DatagramPacket d)   发送数据报包

Socket类,实现客户端套接字。
在构造函数中可以创建与指定的IP地址和端口号连接的套接字。getInputStream 和 getOutputStream 可以得到套接字的输入输出流,用来与服务器端通信。
ServerSocket类,实现服务器端套接字,accept方法侦听并接受到此套接字的连接,返回一个新的套接字,用于服务器和客户端间的通信。

Socket提供了相对较低层的网络通信功能,对于开发来说有更大的扩展性,使用者可以在此基础上编写自己想要的网络应用程序。同时net包下的其他类提供了一种更高层次的因特网访问机制,那就是URL和URLConnection。

URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。一个完整的URL包括协议,主机名,端口号和路径。
URL对象的方法可以返回该URL对象的授权部分(getAuthority),内容(getContent),与此URL关联协议的默认端口号(getDefaultPort),文件名(getFile),主机名(getHost),路径部分(getPath),端口号(getPort),协议名称(getProtocol),查询部分(getQuery),锚点(getRef)和userInfo(getUserInfo)。
openConnection方法返回一个URLConnection对象,表示到URL所引用的远程对象的连接。
openStream方法打开到此URL的连接并返回一个用于从该连接读入的InputStream。

URLConnection类,该抽象类是所有类的超类,代表应用程序和URL之间的通信链接,可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:
  1. 通过在 URL 上调用 openConnection 方法创建连接对象。
  2. 处理设置参数和一般请求属性。
  3. 使用 connect 方法建立到远程对象的实际连接。
  4. 远程对象变为可用。远程对象的头字段和内容变为可访问。

  以前也在学网络编程的时候也尝试写过UDP的聊天程序,不过老师讲的是用c++,我是用java写的。但是最后全班除了我们组是自己写的外,其他组都是从网上down的。因为老师不反对,前提是别人的程序要读懂。可惜老师并不怎么喜欢java,给了我们组比较低的分。

  程序比较简单,没有太复杂的实现,只是简单的实现了聊天功能。但是程序每次启动的时候必须指定一个监听的端口,且之后不能修改监听的端口号。同时还需指定目的端口号,可以在程序运行的过程中修改。关于目的ip地址保存在一个文件中,在界面上显示是通过JComboBox选择的,可以进行添加和删除。同时接收窗口和发送窗口用多线程实现,接收窗口带滚动条,比较容易混淆的一点是,将JTextArea当作参数传给JScrollPanel的构造函数,之后只需将JScrollPanel添加进容器中就可以了,数据仍然添加进JTestArea中。关于滚动条的位置研究了很长时间,还是没弄太清楚。比如在接收框中需要将滚动条一直置在最底部,需将滚动条的值设为最大值setValue(int value),而将滚动条的getMaximum()返回的值带入后滚动条并不是在最底端,奇怪的是当调用两次设置最大值函数后就可以了。

jsb.setValue(jsb.getMaximum());

jsb.setValue(jsb.getMaximum());

不过用google搜到另一个方法可行,将光标放在接收框的末尾,然后调用一次setValue()函数。

jta.setCaretPosition(jta.getDocument().getLength());
jsb.setValue(jsb.getMaximum());
当时为了显示出多线程,还加了一个显示时间的标签,并没有多大实际用处。

JScroll.java

import java.awt.FlowLayout;import java.awt.GridLayout;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;import java.util.Calendar;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollBar;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;public class JScroll extends JPanel implements Runnable{    JPanel subPanel = new JPanel();    JLabel lisLab = null;    JTextField listenport = null;    //JButton btnLis = null;    JTextArea jta = null;    JScrollBar jsb = null;    JScrollPane jsp = null;    DatagramSocket recvSocket = null;    DatagramPacket recvPacket = null;    public JScroll(){        String s = UdpChat.portInput.getText();        int ss = 0;        try{            ss = Integer.parseInt(s);        }catch(NumberFormatException e){            System.out.println("listening port must be a integer!");            ss = 52525;        }finally{            if(ss>65535 || ss<1){                s = "52525";            }        }        subPanel.setLayout(new GridLayout(3,1));        this.setLayout(new FlowLayout(FlowLayout.TRAILING));        lisLab = new JLabel("listen port↓");        listenport = new JTextField(7);        listenport.setText(ss+"");        listenport.setEditable(false);        jta = new JTextArea(12,55);        jta.setLineWrap(true);        jta.setEditable(false);        jsp = new JScrollPane(jta);        jsb = jsp.getVerticalScrollBar();        jta.setEditable(false);        subPanel.add(lisLab);        subPanel.add(listenport);        this.add(jsp);        this.add(subPanel);    }    public String formatTime(int t){        String r ="00";        if(t<10){            r = "0"+t;        }else{            r = "" + t;        }        return r;    }    public void run() {        String p = listenport.getText();        int port1 = Integer.parseInt(p);                byte buf[] = new byte[1024*8];        try {            recvSocket = new DatagramSocket(port1);        } catch (SocketException e1) {            e1.printStackTrace();        }        recvPacket = new DatagramPacket(buf, buf.length);        while(true){            try {                recvSocket.receive(recvPacket);                Calendar cal = Calendar.getInstance();                int hour = cal.get(Calendar.HOUR_OF_DAY);                int min = cal.get(Calendar.MINUTE);                int sec = cal.get(Calendar.SECOND);                String h,m,s;                h = formatTime(hour);                m = formatTime(min);                s = formatTime(sec);                String ip = recvPacket.getAddress().getHostAddress();                int port = recvPacket.getPort();                String msg = new String(buf,0,recvPacket.getLength());                jta.append("msg from ip-【"+ip+":"+port+"】@"+h+":"+m+":"+s+"\r\n"+msg+"\r\n");                jta.setCaretPosition(jta.getDocument().getLength());                jsb.setValue(jsb.getMaximum());                //jsb.setValue(jsb.getMaximum());                msg = "";            } catch (IOException e) {                e.printStackTrace();            }           }    }}


TimeLable.java

import java.net.InetAddress;import java.net.UnknownHostException;import java.util.Calendar;import javax.swing.JLabel;class TimeLabel extends JLabel implements Runnable{    private static final long serialVersionUID = 1L;    /**     * 覆盖Runnable接口的run()方法,此为该线程要运行的代码<br/>     * */    public void run() {        /**/Calendar cal = Calendar.getInstance();        int hour = cal.get(Calendar.HOUR_OF_DAY);        int min = cal.get(Calendar.MINUTE);        int sec = cal.get(Calendar.SECOND);        int msec = 0;        while(true){            String h,m,s,ms;            h = hour+"";            m = min+"";            s = sec+"";            ms = msec+"";            if(msec<10){                ms = "0"+msec;            }            if(sec<10){                s = "0"+sec;            }            if(min<10){                m = "0"+min;            }            this.setHorizontalAlignment(RIGHT);            try {                this.setText(InetAddress.getLocalHost().getHostAddress()+"//"+"系统时间-"+h+":"+m+":"+s+":"+ms);            } catch (UnknownHostException e1) {                e1.printStackTrace();            }            try {                Thread.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }            if(msec==99){                if(sec==59){                    if(min==59){                        hour++;                        min=0;                        sec=0;                        msec=0;                    }                    else{                        min++;                        sec=0;                        msec=0;                    }                }                else{                    sec++;                    msec=0;                }            }            else{                msec++;            }        }    }}

UdpChat.java

import java.awt.BorderLayout;import java.awt.Container;import java.awt.FlowLayout;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;import java.util.regex.Pattern;import javax.swing.JButton;import javax.swing.JComboBox;import javax.swing.JDialog;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollBar;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;public class UdpChat {    JDialog jd = new JDialog(new JFrame(),"PORT",true);    public static JTextField portInput = null;    public static JTextField portInput2 = null;    JLabel labPort = null;    JLabel labPort2 = null;    JButton btnOk = null;    JButton btnNo = null;    public UdpChat(){        jd.setLayout(new GridLayout(3,2));        labPort = new JLabel("listenning port:");         labPort2 = new JLabel("destination port:");        portInput = new JTextField(6);        portInput2 = new JTextField(6);        btnOk = new JButton("OK");        btnNo = new JButton("NO");        jd.add(labPort);        jd.add(portInput);        jd.add(labPort2);        jd.add(portInput2);        jd.add(btnOk);        jd.add(btnNo);        startEvents();        jd.setBounds(520, 250, 300, 150);        jd.setVisible(true);    }    public void startEvents(){        btnNo.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                System.exit(0);            }        });        btnOk.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                jd.setVisible(false);                new UdpSend();            }        });    }    public static void main(String[] args) {        new UdpChat();    }}class UdpSend extends JFrame{    Container cont = this.getContentPane();        JPanel jpanel = new JPanel();    JLabel ipLabel = null;    JTextField ipInput = null;    JButton btnAdd = null;    JLabel portLabel = null;    JTextField portField = null;    JLabel ipsLabel = null;    JComboBox ipBox = null;    JButton btnDel = null;    JButton btnClearAll = null;    JPanel msgPanel = new JPanel();    JScroll recv = null;    JTextArea send = null;    JScrollPane jsp = null;    JScrollBar jsb = null;    JPanel btnPanel = new JPanel();    TimeLabel time = null;    JLabel labNull = null;    JButton btnSend = null;    JButton btnClose = null;      DatagramSocket sendSocket = null;    DatagramPacket sendPacket = null;    public UdpSend(){        cont.setLayout(new BorderLayout());        jpanel.setLayout(new FlowLayout());        msgPanel.setLayout(new FlowLayout());        btnPanel.setLayout(new FlowLayout());        ipLabel = new JLabel("des ip:");        ipInput = new JTextField(12);        btnAdd = new JButton("add");        portLabel = new JLabel("des port:");        portField = new JTextField(5);        String s = UdpChat.portInput2.getText();        int ss = 0;        try{            ss = Integer.parseInt(s);        }catch(NumberFormatException e){            System.out.println("destination port must be a integer!");            ss = 52525;        }finally{            if(ss>65535 || ss<1){                s = "52525";            }        }        portField.setText(ss+"");        ipsLabel = new JLabel("ip sets:");        ipBox = new JComboBox(readIp());        ipBox.setEditable(false);        btnDel = new JButton("delete");        btnClearAll = new JButton("clear all");                jpanel.add(ipLabel);        jpanel.add(ipInput);        jpanel.add(btnAdd);        jpanel.add(portLabel);        jpanel.add(portField);        jpanel.add(ipsLabel);        jpanel.add(ipBox);        jpanel.add(btnDel);        jpanel.add(btnClearAll);                recv = new JScroll();        msgPanel.add(recv);        Thread recvThread = new Thread(recv);        recvThread.start();        send = new JTextArea(5,63);        send.setLineWrap(true);        jsp = new JScrollPane(send);        jsb = jsp.getVerticalScrollBar();        msgPanel.add(jsp);                        time = new TimeLabel();        Thread timeThread = new Thread(time);        timeThread.start();        labNull = new JLabel("                                                                                                                         ");        //文件传输功能赞不可用,未实现!!        //filePath = new JTextField(15);        //btnTransFile = new JButton("send file");        btnSend = new JButton("send");        btnClose = new JButton("close");        btnPanel.add(time);        btnPanel.add(labNull);        //文件传输功能赞不可用,未实现!!        //btnPanel.add(filePath);        //btnPanel.add(btnTransFile);        btnPanel.add(btnSend);        btnPanel.add(btnClose);                        this.add(jpanel,BorderLayout.NORTH);        this.add(msgPanel,BorderLayout.CENTER);        this.add(btnPanel,BorderLayout.SOUTH);        events();        this.setBounds(350, 150, 720, 450);        this.setResizable(false);        this.setVisible(true);        this.setDefaultCloseOperation(EXIT_ON_CLOSE);        }        //事件    public void events(){        btnAdd.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                String inputIp = ipInput.getText();                FileWriter fw = null;                try {                    fw = new FileWriter("ip",true);                    //System.out.println("hello");                } catch (IOException e1) {                    e1.printStackTrace();                }                if( ipReg(inputIp)){                    ipBox.addItem(inputIp);                    try {                        fw.write(inputIp+"\r\n");                        fw.flush();                    } catch (IOException e1) {                        e1.printStackTrace();                    }finally{                        if(fw!=null){                            try{                                fw.close();                            }catch(IOException e2){                                e2.printStackTrace();                            }                        }                    }                }                ipInput.setText("");            }        });        btnDel.addActionListener(new ActionListener() {            @SuppressWarnings("resource")            public void actionPerformed(ActionEvent e) {                Object obj = ipBox.getSelectedItem();                ipBox.removeItem(obj);                int ipCount = ipBox.getItemCount();                File f = new File("ip");                if(f.exists()){                    f.delete();                }                BufferedWriter bw = null;                try {                    bw = new BufferedWriter(new FileWriter("ip"));                    for(int i=0;i<ipCount;i++){                        String ip = (String)ipBox.getItemAt(i);                        bw.write(ip+"\r\n");                        bw.flush();                    }                } catch (IOException e1) {                    e1.printStackTrace();                }finally{                    if(bw!=null){                        try{                            bw.close();                        }catch(IOException e2){                            e2.printStackTrace();                        }                    }                }            }        });        btnClearAll.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                ipBox.removeAllItems();                File f = new File("ip");                if(f.exists()){                    f.delete();                }            }        });        btnSend.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                                String s = rapString(send.getText());                recv.jta.append(s);                sendMsg();            }        });        btnClose.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                closeSocket();                System.exit(0);            }        });    }    @SuppressWarnings("resource")    public String[] readIp(){        String[] ips = new String[50];        String[] temp = null;        String[] a = {""};        int ipCount = 0;        File f = new File("ip");        BufferedReader br = null;        if(f.exists()){            try {                br = new BufferedReader(new FileReader("ip"));                while(true){                    try {                        String ip = br.readLine();                        if(ip!="" && ip!=null && ipCount<50){                            ips[ipCount]=ip;                            ipCount++;                        }                        if(ip==null){                            break;                        }                    } catch (IOException e) {                        e.printStackTrace();                    }                }            } catch (FileNotFoundException e) {                e.printStackTrace();            }finally{                temp = new String[ipCount];                for(int i=0 ;i<ipCount;i++){                    temp[i] = ips[i];                }                if(br!=null)                    try{                        br.close();                    }catch(IOException e){                        e.printStackTrace();                    }            }            return temp;        }else{            return a;        }            }    public void closeSocket(){        if(sendSocket!=null){            sendSocket.close();        }    }    public void sendMsg(){        String ip = (String) ipBox.getSelectedItem();        int port = Integer.parseInt(portField.getText());        byte []buf = send.getText().getBytes();        try {            sendSocket = new DatagramSocket();            sendPacket = new DatagramPacket(buf, 0, buf.length,InetAddress.getByName(ip),port);             try {                 sendSocket.send(sendPacket);                 send.setText("");            } catch (IOException e) {                e.printStackTrace();            }        } catch (SocketException e) {            e.printStackTrace();        } catch (UnknownHostException e) {            e.printStackTrace();        }    }public String rapString(String msg){    String head="",foot="";    for(int i=0;i<50;i++){        head = head + "_";    }    for(int j=0;j<50;j++){        foot = foot + " ̄";    }    msg = head+ "\r\nLOCALHOST:" + msg + "\r\n" +foot + "\r\n";    return msg;    }public boolean ipReg(String ip){                boolean flag =Pattern.matches("(\\d{1,3}\\.){3}\\d{1,3}",ip);        if(flag){            //split(String regex)用”.“分割,正则表达式里.表示任何字符,需要用\转义,java里\又需要用\来转义,所以此处要两个\。            String s[] = ip.split("\\.");            for(int i =0 ;i<s.length;i++){                if(Integer.parseInt(s[i])>255){                    flag = false;                }            }        }        return flag;    }}

  TCP和UDP的聊天程序大同小异,不同的是TCP是面向连接的,UDP是面向无连接的,TCP好比打电话,双方确认连接后能通信,UDP好比寄信,只管发送,并不管目的地址是否存在或者能否信件能否送到。TCP编程中若要判断当前连接数,无法通过Socket类对象的isClosed或者isConneced方法来判断,这两个方法只能判断本地socket 的连接状况,不能判断远程的状态。比如客户端断开后,服务器端不能通过调用这两个方法来判断客户端的状态。若socket对象的setKeepAlive(boolean on)置为true,本地主机会隔一段时间(由系统内核参数配置)向远程主机发送一个数据包用于检测连接是否存活。另一种常用的检测连接是否存活的方法是使用心跳包,服务器或客户端每隔一段时间向远程主机发送一段数据,若远程主机给予回应则表示连接存活。(心跳包这一部分正在学习中。。。)

下面通过URL连接来获取指定url上的内容:

   
public static void main(String[] args) throws IOException {        //创建指定的URL地址        URL url = new URL("http://bbs.itheima.com/forum-142-1.html");        //打开连接        URLConnection conn = url.openConnection();        //获得读取流        BufferedInputStream bufin = new BufferedInputStream(conn.getInputStream());        //读取数据        int len = 0;        byte buf[] = new byte[1024];        while((len = bufin.read(buf)) != -1){            System.out.println(new String(buf,0,len,"UTF-8"));        }    }


但是获取到的都是html文档内容,无法解析,如果是在浏览器上就能解析了。

public static void main(String[] args) throws IOException {        while(true){            //监听指定端口            ServerSocket server = new ServerSocket(8181);            //和客户端建立连接            Socket client = server.accept();            //获取输入流,封装输入流            BufferedReader bufr = new BufferedReader(new InputStreamReader(client.getInputStream()));            //获取输出流,封装输出流            BufferedOutputStream buf_out = new BufferedOutputStream(client.getOutputStream());            //将客户端需要访问的地址切割出来            String content = bufr.readLine();            String urlString = content.substring(content.indexOf("/")+1,content.lastIndexOf(" "));            //将地址封装成URL对象            URL url = new URL("http://" + urlString);            //打开URL连接            URLConnection con = url.openConnection();            //获取输入流,读取数据            BufferedInputStream bufin = new BufferedInputStream(con.getInputStream());            int len = 0;            byte buf[] = new byte[1024];            while((len = bufin.read(buf)) != -1){                //将数据写给浏览器,刷新                buf_out.write(buf, 0, len);                buf_out.flush();            }            //关闭流            bufin.close();            bufr.close();            buf_out.close();            client.close();            server.close();        }    }


  首先这个程序并没有实际意义,主要是能巩固一下Socket,URL和IO的用法。客户端在访问服务器时将需要访问的地址一并传给服务器,服务器将需要访问的地址切割出来,封装成URL对象,打开连接并获取数据,然后再将数据写给浏览器。但是在用火狐浏览器时,火狐浏览器并没有将html文档进行解析,而是原封不动的显示出来。用IE内核的浏览器可以解析,但是图片不能显示。

原创粉丝点击