Java基础之网络编程

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

一、因特网

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

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

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

我们熟悉的因特网就是有无数的广域网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 stub
		InetAddress ip;
		try {
			//实例化对象
			ip=InetAddress .getLocalHost();
			//获取本机名
			String localName=ip.getHostName();
			//获取本机地址
			String localIP=ip.getHostAddress();
			System.out.println("本机名是:"+localName+"\n"+"主机地址是:"+localIP);
		} catch (Exception e) {
			// TODO: handle exception
			e.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 stub
		new 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() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				pw.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 stub
		TCPClientDemo 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 exception
			e.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 stub
		new 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 exception
			e.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;
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if(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 stub
		new UDPReceiveDemo().setSize(460,200);

	}

}

运行结果:

发送端:



接收端:







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值