Java基础之网络编程

来源:互联网 发布:刺客信条优化最好的 编辑:程序博客网 时间:2024/05/17 01:59

网络编程就是编写与其他计算机进行通信的程序,是两机进行通讯。

一、因特网

为了实现两台计算机的通信,必须要用一个网络线路来连接两台计算机。

连接模式就是   服务器---------网络----------客户机

所谓的服务器就是提供和处理信息的计算机或程序,而客户机是指请求信息的计算机或程序。网络用于连接两者,实现服务器与客户机的通信。这里的网络就是因特网了。

我们熟悉的因特网就是有无数的广域网LAN和局域网WAN组成的。

二、网络协议

1、ip协议

IP是一种网络协议,它是Internet Protocol的简称。Internet网络采用的是TCP/IP协议,依靠它,在全球范围上实现不同硬件结构、不同操作系统、不同网络系统的互联。这就有了相对应的IP地址来表示自己的机器。到目前为止,IP地址用4个字节,32位二进制数来表示称为IPv4。为了方便使用,每个字节就用十进制来表示。如192.168.12.26 。

TCP/IP是一个层次参考模型,共分为4层。分别为应用层,传输层,互联网层和网络层。各层实现特定的功能,提供特定的服务和访问接口。

2、TCP与UDP协议

在TCP/IP协议中有两个高级协议,就是TCP协议即传输控制协议和UDP协议即用户数据报协议。

TCP是一种面向连接的协议,提供可靠的数据传送,并且能够保证数据从一端完好无损的到达另一端,所以说TCP协议适合可靠性要求高的场合,比如打电话。

UDP是一种面向无连接的协议,数据传输不可靠,但是可以向多个目标发送数据,也可以接收多个目标发送过来的数据。可见,UDP协议适合一些对数据准确性不高的场合,如网络聊天室。

所以TCP与UDP的区别如下:

TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。

UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。

三、端口号和套接字

一般而言,一台计算机只有单一的连接到网络的物理连接,所有的数据都通过此链接进行数据的收发,这就是端口。端口不是真实存在的,而是一个逻辑的连接装置。端口号被规定为0-65536之间的整数。通常0-1024使系统使用的端口,1024之后是用户使用应用程序的端口。

套接字用于应用程序与端口号的连接,套接字也是一个假象的装置,就向插头与插座的关系一样。

四、TCP设计

TCP设计师之利用Socket类编写通信程序。利用TCP协议进行通信的两个程序是有主次之分的,一个称为服务器程序,一个称为客户端程序。

1、InetAdress类

示例:使用InetAdress类中的getHostName()和GetHostAddress()方法获得本机的主机名和主机地址。

package com.heima.net;import java.net.*;/** * 使用InetAdress类中的getHostName()和GetHostAddress()方法获得本机的主机名和主机地址。 * @author Administrator * */public class AddressnetDemo {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubInetAddress ip;try {//实例化对象ip=InetAddress .getLocalHost();//获取本机名String localName=ip.getHostName();//获取本机地址String localIP=ip.getHostAddress();System.out.println("本机名是:"+localName+"\n"+"主机地址是:"+localIP);} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}}
运行结果:


2、ServerSocket类

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

ServerSocket类的常用方法:

1)、accept()   等待客户机连接,如成功,就会返回一个Socket类型的套接字。

2)、isBounds() 判断ServerSocket的绑定状态,返回boolean类型。

3)、getInetAdress() 返回服务器套接字的本地地址。

4)、close() 关闭服务器。

调用ServerSocket类中的accept方法会返回一个和客户机Socket对象相连接的Socket对象,同样,服务器端的Socket对象实用的getInputStream方法的输入流指向客户端socket对象使用getOutputStream()方法获得输出流。也就是说服务器和客户端都能够读取从对方发过来的信息。

注意:accept方法会堵塞线程执行,直到收到客户端的呼叫,否则下面的语句不会执行。

3、TCP程序示例:

服务器端程序:

package com.heima.net;import java.io.*;import java.net.*;/** * 编写一个服务器端程序,用来接收客户端发过来的信息 * @author Administrator * */public class TCPServerDemo {private ServerSocket server;private Socket socket;private BufferedReader br;public void getSerVer(){try {server=new ServerSocket(3456);System.out.println("服务器创建成功");while(true){System.out.println("等待客户端连接");socket=server.accept();br=new BufferedReader(new InputStreamReader(socket.getInputStream()));String str;while((str=br.readLine())!=null){System.out.println("客户端:"+str);}}} catch (Exception e) {// TODO: handle exception}}public static void main(String[] args) {// TODO Auto-generated method stubnew TCPServerDemo().getSerVer();}}

客户端程序:

package com.heima.net;import java.awt.BorderLayout;import java.awt.Container;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.PrintWriter;import java.net.Socket;import javax.swing.*;import javax.swing.border.BevelBorder;/* * 编写客户端程序,实现用户在文本框输入信息后将信息发送至服务器端 */public class TCPClientDemo extends JFrame{private PrintWriter pw;private Socket socket;private JTextArea ta=new JTextArea();private JTextField tf=new JTextField();private Container ct;TCPClientDemo(String str){super(str);this.setDefaultCloseOperation(EXIT_ON_CLOSE);ct=this.getContentPane();final JScrollPane sp=new JScrollPane();sp.setBorder(new BevelBorder(BevelBorder.RAISED));getContentPane().add(sp,BorderLayout.CENTER);sp.setViewportView(ta);ct.add(tf,"South");tf.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubpw.println(tf.getText());ta.append(tf.getText()+"\n");ta.setSelectionEnd(ta.getText().length());tf.setText("");}});}private void connect(){ta.append("尝试连接服务器\n");try {socket=new Socket("127.0.0.1",3456);pw=new PrintWriter(socket.getOutputStream(),true);ta.append("连接服务器成功\n");} catch (Exception e) {// TODO: handle exception}}public static void main(String[] args) {// TODO Auto-generated method stubTCPClientDemo client=new TCPClientDemo("向服务器发送信息");client.setSize(200,200);client.setVisible(true);client.connect();}}

程序先运行服务器,后运行客户端结果是:




五、UDP设计

用户数据报协议(UDP)是网络传输的另一种形式,相比于TCP传输,UDP的信息传递速率快,但是可靠性不高,使用UDP传输数据,用户不知道数据能否到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。虽然UDP是一个不可靠的协议,但如果需要较快的传输信息,并能容忍信息丢失,就可以用UDP协议传输数据。

UDP的通信模式就是   1,将数据打包,然后发送至目的地。2,接收别人发过来的数据包,然后查看。

具体步骤如下:

(1)发送数据包:

使用DatagramSocket()创建套接字;使用DatagramPacket(byte[] buf,int length,InetAddress ip,int port)创建要发送的数据包;使DatagramSocket的send()方法发送数据包。

(2)接收数据包:

使用DatagramSocket(int port)创建套接字,并绑定到指定端口;使用DatagramPacket(byte[] buf,int length)创建字节数组来接收数据包;使用DatagramSocket的receive()方法接收数据包。

1、DatagramPacket类

这是一个用来表示数据包的类。它的构造函数如下:

DatagramPacket(byte[] buf,int length)

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

第一种创建了DatagramPacket对象,制订了数据包的内存空间大小。第二种不仅是定了空间大小,还指定了数据包的目的地址和端口号。在发送数据时一定要指定目的地址和端口号。

2、DatagramSocket类

此类用于表示发送和接收数据包的套接字。该类的构造函数有:

DatagramSocket();

DatagramSocket(int port)

DatagramSocket(int port InetAddress ip)

第一种创建DatagramSocket对象,构造数据报套接字并将其绑定到本地主机的任何可用端口上。第二种是绑定到本地地址的指定端口上。第三种是绑定到指定地址的指定端口上。

在接受程序中,必须指定一个端口号,在发送程序中,通常不必指定端口号,就跟寄信不需要指定哪个邮局寄信一样。

3、UDP程序实例

发送端代码:

package com.heima.net;import java.net.*;/* * 编写一个广播数据报程序,实现同一组的主机可以接受到广播信息 */public class UDPSendDemo extends Thread {String str="通知:今晚八点有会,请注意收听";int port=6666;//定义端口号InetAddress ip=null;MulticastSocket socket=null;//创建多点广播套接字UDPSendDemo(){try {ip=InetAddress.getByName("224.255.10.0");//实例化多点广播套接字socket=new MulticastSocket(port);//指定发送范围是本地网络socket.setTimeToLive(1);//加入广播组socket.joinGroup(ip);} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}public void run(){while(true){DatagramPacket dp=null;byte[] data=str.getBytes();//数据打包dp=new DatagramPacket(data, data.length, ip, port);System.out.println(new String(data));//发送数据包try {socket.send(dp);sleep(1000);} catch (Exception e) {// TODO: handle exception}}}public static void main(String[] args) {// TODO Auto-generated method stubnew UDPSendDemo().start();}}

接收端代码:

package com.heima.net;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Container;import java.awt.GridLayout;import java.awt.Point;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.DatagramPacket;import java.net.InetAddress;import java.net.MulticastSocket;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JScrollBar;import javax.swing.JScrollPane;import javax.swing.JSpinner;import javax.swing.JTextArea;public class UDPReceiveDemo extends JFrame implements Runnable ,ActionListener{/** * @param args */int port;InetAddress ip=null;MulticastSocket socket=null;JButton sta=new JButton("开始接受");JButton stop=new JButton("停止接受");JTextArea incear=new JTextArea(10,10);JTextArea inced=new JTextArea(10,10);Thread thread;boolean b=false;UDPReceiveDemo(){super("广播数据报");this.setDefaultCloseOperation(EXIT_ON_CLOSE);thread=new Thread(this);sta.addActionListener(this);stop.addActionListener(this);incear.setForeground(Color.blue);JPanel north=new JPanel();north.add(sta);north.add(stop);add(north,BorderLayout.NORTH);JPanel center=new JPanel();center.setLayout(new GridLayout(1,2));center.add(incear);JScrollPane sp=new JScrollPane(inced);////    JScrollBar bar=sp.getVerticalScrollBar();////    bar.setValue(bar.getMaximum());//Point p = new Point();//     p.setLocation(0, inced.getLineCount() * 20);//     JScrollBar bar=sp.getVerticalScrollBar();//     bar.setValue(p.y);center.add(sp);add(center,BorderLayout.CENTER);validate();port=6666;try {ip=InetAddress.getByName("224.255.10.0");socket=new MulticastSocket(port);socket.joinGroup(ip);} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}setBounds(100,50,360,380);setVisible(true);}public void run(){while(true){byte[] data=new byte[1024];DatagramPacket dp=new DatagramPacket(data, data.length,ip,port);try {socket.receive(dp);String message=new String(dp.getData(),0,dp.getLength());incear.setText("正在接收的信息是\n"+message);inced.append(message+"\n");} catch (Exception e) {// TODO: handle exception}if(b==true)break;}}@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubif(e.getSource()==sta){sta.setBackground(Color.red);stop.setBackground(Color.yellow);if(!thread.isAlive()){thread=new Thread(this);}thread.start();b=false;}else {sta.setBackground(Color.yellow);stop.setBackground(Color.red);b=true;}}public static void main(String[] args) {// TODO Auto-generated method stubnew UDPReceiveDemo().setSize(460,200);}}

运行结果:

发送端:



接收端:







0 0