学生个人网站建设方案书框架栏目,长沙推广公司,销售找客户最好的app,广东东莞人才招聘网计算机网络实现了多台计算机间的互联#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序#xff0c;这些程序借助于网络协议#xff0c;相互之间可以交换数据。编写网络应用程序前#xff0c;首先必须明确所要使用的网络协议…计算机网络实现了多台计算机间的互联使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序这些程序借助于网络协议相互之间可以交换数据。编写网络应用程序前首先必须明确所要使用的网络协议。TCP/IP协议是网络应用程序的首选
一.网络程序设计基础\
网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装成不同的类用户只要创建这些类的对象使用相应的方法即使不具备有关的网络知识也可以编写出高质量的网络通信程序。
1.局域网与互联网
为了实现两台计算机的通信必须用一个网络线路连接两台计算机 服务器是指提供信息的计算机或程序客户机是指请求信息的计算机或程序。网络用于连接服务器与客户机实现两者间的相互通信。但是有时在某个网络中很难将服务器与客户机区分开。我们通常所说的局域网Local Area NetworkLAN就是一群通过一定形式连接起来的计算机它可以由两台计算机组成也可以由同一区域内的上千台计算机组成。将LAN延伸到更大的范围这样的网络称为广域网Wide Area NetworkWAN。我们熟悉的互联网Internet就是由无数的LAN和WAN组成的。
2.网络协议
网络协议规定了计算机之间连接的物理、机械网线与网卡的连接规定、电气有效的电平范围等特征计算机之间的相互寻址规则数据发送冲突的解决方式长数据如何分段传送与接收等内容。就像不同的国家有不同的法律一样目前网络协议也有多种。下面简单地介绍几个常用的网络协议。
1IP协议
IP是Internet Protocol的简称是一种网络协议。Internet网络采用的协议是TCP/IP协议其全称是Transmission Control Protocol/Internet Protocol。Internet依靠TCP/IP协议在全球范围内实现了不同硬件结构、不同操作系统、不同网络系统间的互联。在Internet网络上存在着数以亿计的主机每台主机都用网络为其分配的Internet地址代表自己这个地址就是IP地址。到目前为止IP地址用4个字节也就是32位的二进制数来表示称为IPv4。为了便于使用通常取用每个字节的十进制数并且每个字节之间用圆点隔开来表示IP地址如192.168.1.1。现在人们正在试验使用16个字节来表示IP地址这就是IPv6但IPv6还没有投入使用。
TCP/IP模式是一种层次结构共分为4层分别为应用层、传输层、互联网层和网络层。各层实现特定的功能提供特定的服务和访问接口并具有相对的独立性。
2TCP与UDP协议
在TCP/IP协议栈中有两个高级协议是网络应用程序编写者应该了解的即传输控制协议Transmission Control ProtocolTCP与用户数据报协议User Datagram ProtocolUDP。
TCP协议是一种以固接连线为基础的协议它提供两台计算机间可靠的数据传送。TCP可以保证数据从一端送至连接的另一端时能够确实送达而且抵达的数据的排列顺序和送出时的顺序相同。因此TCP协议适合可靠性要求比较高的场合。就像拨打电话必须先拨号给对方等两端确定连接后相互才能听到对方说话也知道对方回应的是什么。
HTTP、FTP和Telnet等都需要使用可靠的通信频道。例如HTTP从某个URL读取数据时如果收到的数据顺序与发送时不相同可能就会出现一个混乱的HTML文件或是一些无效的信息。
UDP是无连接通信协议不保证数据的可靠传输但能够向若干个目标发送数据或接收来自若干个源的数据。UDP以独立发送数据包的方式进行。这种方式就像邮递员送信给收信人可以寄出很多信给同一个人且每一封信都是相对独立的各封信送达的顺序并不重要收信人接收信件的顺序也不能保证与寄出信件的顺序相同。
UDP协议适合于一些对数据准确性要求不高但对传输速度和时效性要求非常高的网站如网络聊天室、在线影片等。这是由于TCP协议在认证上存在额外耗费可能使传输速度减慢而UDP协议即使有一小部分数据包遗失或传送顺序有所不同也不会严重危害该项通信。 注意
一些防火墙和路由器会设置成不允许UDP数据包传输因此若遇到UDP连接方面的问题应先确定所在网络是否允许UDP协议 3.端口与套接字
一般而言一台计算机只有单一的连到网络的物理连接Physical Connection所有的数据都通过此连接对内、对外送达特定的计算机这就是端口。网络程序设计中的端口port并非真实的物理存在而是一个假想的连接装置。端口被规定为一个在065535的整数。HTTP服务一般使用80端口FTP服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务那么客户机会通过不同的端口来确定连接到服务器的哪项服务上如图21.3所示。
通常01023的端口数用于一些知名的网络服务和应用用户的普通网络应用程序应该使用1024以上的端口数以避免端口号与另一个应用或系统服务所用端口冲突。
网络程序中的套接字Socket用于将应用程序与端口连接起来。套接字是一个假想的连接装置就像插座一样可连接电器与电线如图21.4所示。Java将套接字抽象化为类程序设计者只需创建Socket类对象即可使用套接字。 二.TCP程序
TCP网络程序设计是指利用Socket类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的一个称为服务器程序另一个称为客户机程序两者的功能和编写方法大不一样。 1.InetAddress类
java.net包中的InetAddress类是与IP地址相关的类利用该类可以获取IP地址、主机地址等信息。 使用InetAddress类的getHostName()和getHostAddress()方法获得本地主机的本机名、本机IP地址。
package wanluo;import java.net.*; //导入Java.net包public class Address {//创建类public static void main(String[] args) {InetAddress ip;//创建InetAddress对象try {//捕捉可能出现的异常 ip InetAddress.getLocalHost();//实例化对象String IocaIname ip.getHostName();//获取本机名String Iocalip ip.getHostAddress();//获取本机IP地址System.out.println(本机名 IocaIname);//将本机名输出System.out.println(本机IP地址 Iocalip);//将本机IP地址输出}catch(UnknownHostException e) {e.printStackTrace();//输出异常信息}}
}结果如下 2.ServerSocket类
java.net包中的ServerSocket类用于表示服务器套接字其主要功能是等待来自网络上的“请求”它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求服务器套接字会将请求连接的客户机存入列队中然后从中取出一个套接字与服务器新建的套接字连接起来。若请求连接数大于最大容纳数则多出的连接请求被拒绝。队列的默认大小是50。 ServerSocket类的构造方法通常会抛出IOException异常具体有以下几种形式
ServerSocket()创建非绑定服务器套接字。ServerSocket(int port)创建绑定到特定端口的服务器套接字。ServerSocket(int port, int backlog)利用指定的backlog创建服务器套接字并将其绑定到指定的本地端口号上。ServerSocket(int port, int backlog, InetAddress bindAddress)使用指定的端口、侦听backlog和要绑定到的本地IP地址创建服务器。这种情况适用于计算机上有多块网卡和多个IP地址的情况用户可以明确规定ServerSocket在哪块网卡或哪个IP地址上等待客户的连接请求。 调用ServerSocket类的accept()方法会返回一个和客户端Socket对象相连接的Socket对象。服务器端的Socket对象使用getOutputStream()方法获得的输出流将指向客户端Socket对象使用getInputStream()方法获得的那个输入流同样服务器端的Socket对象使用getInputStream()方法获得的输入流将指向客户端Socket对象使用getOutputStream()方法获得的那个输出流。也就是说当服务器向输出流写入信息时客户端通过相应的输入流就能读取反之亦然。 注意
accept()方法会阻塞线程的继续执行直到接收到客户的呼叫。如果没有客户呼叫服务器那么System.out.println(连接中)语句将不会执行。语句如果没有客户请求accept()方法没有发生阻塞肯定是程序出现了问题。通常是使用了一个被其他程序占用的端口号ServerSocket绑定没有成功。
yu server.accept();
System.out.println(连接中); 3.TCP网络程序设计
明白了TCP程序工作的过程就可以编写TCP服务器程序了。在网络编程中如果只要求客户机向服务器发送消息不要求服务器向客户机发送消息称为单向通信。客户机套接字
和服务器套接字连接成功后客户机通过输出流发送数据服务器则通过输入流接收数据。下面是简单的单向通信的实例。
例题21.2:创建TCP/IP协议服务器
package wanluo;import java.io.*;
import java.net.*;public class MyServer {private ServerSocket server;//服务器套接字private Socket socket;//客户机套接字void start() {//启动服务器try {server new ServerSocket(5555);//服务器启用5555端口System.out.println(服务器套接字已经创建成功);while(true){System.out.println(等待客户机的连接);socket server.accept();//服务器监听客户机连接BufferedReader reader new BufferedReader(new InputStreamReader(socket.getInputStream()));while(true) {//循环接收信息String message reader.readLine();//读取一行文本if(exit.equals(message)) {//如果客户机发来的内容为exitSystem.out.println(客户机退出);break;//停止接收信息}System.out.println(客户机 message);}reader.close();//关闭流socket.close();//关闭套接字}}catch(IOException e) {e.printStackTrace();}}public static void main(String[] args) {MyServer tcp new MyServer();tcp.start();//启动服务器}}结果如下 运行服务器端程序将输出提示信息等待客户呼叫。下面再来看一下客户端程序。
编写客户端程序将用户在文本框中输入的信息发送至服务器端并将文本框中输入的信息显示在客户端的文本域中。
package wanluo;import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.Socket;
import javax.swing.*;public class MyClient extends JFrame{private PrintWriter writer;//根据套接字字节流创建的字符输出流Socket socket;//客户端套接字private JTextArea area new JTextArea();//展现信息的文本域private JTextField text new JFormattedTextField();//发送信息的文本框public MyClient() {setTitle(向服务器送数据);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Container c getContentPane();//主容器JScrollPane sctollPane new JScrollPane(area);//滚动面板getContentPane().add(sctollPane,BorderLayout.CENTER);c.add(text,South);//将文本框放在窗体的下部text.addActionListener(new ActionListener() {//文本框触发回车事件Overridepublic void actionPerformed(ActionEvent e) {writer.println(text.getText().trim());//将文本框中的信息写入流area.append(text.getText() \n);//将文本框中的信息显示在文本域中text.setText();//将文本框清空}});}private void connect() {//连接服务器方法area.append(尝试连接\n);//文本域提示信息try {socket new Socket(127.0.0.1,5555);//连接本地计算机的5555端口writer new PrintWriter(socket.getOutputStream(),true);area.append(完成连接\n);}catch(IOException e) {e.printStackTrace();}}public static void main(String[] args) {MyClient clien new MyClient();//窗体大小clien.setSize(200,200);//显示窗体clien.setVisible(true);//连接服务器clien.connect();}}
结果如下 说明
当一台机器上安装了多个网络应用程序时很可能指定的端口号已被占用。还可能遇到以前运行良好的网络程序突然运行不了的情况这种情况很可能也是由于端口被别的程序占用了。此时可以运行netstat-help来获得帮助使用netstat-an命令来查看该程序所使用的端口 三.UDP程序 用户数据报协议UDP是网络信息传输的另一种形式。基于UDP的通信和基于TCP的通信不同基于UDP的信息传递更快但不提供可靠性保证。使用UDP传递数据时用户无法知道数据能否正确地到达主机也不能确定到达目的地的顺序是否和发送的顺序相同。虽然UDP是一种不可靠的协议但如果需要较快地传输信息并能容忍小的错误可以考虑使用UDP。
基于UDP通信的基本模式如下 将数据打包称为数据包然后将数据包发往目的地。 接收别人发来的数据包然后查看数据包。
发送数据包的步骤如下
1使用DatagramSocket()创建一个数据包套接字。
2使用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)创建要发送的数据包。
3使用DatagramSocket类的send()方法发送数据包。
接收数据包的步骤如下
使用DatagramSocket(int port)创建数据包套接字绑定到指定的端口。使用DatagramPacket(byte[] buf, int length)创建字节数组来接收数据包。使用DatagramPacket类的receive()方法接收UDP包。
注意
DatagramSocket类的receive()方法接收数据时如果还没有可以接收的数据在正常情况下receive()方法将阻塞一直等到网络上有数据传来receive()方法接收该数据并返回。如果网络上没有数据发送过来receive()方法也没有阻塞肯定是程序有问题大多数情况下是因为使用了一个被其他程序占用的端口号。
1.DatagramPacket类 java.net包的DatagramPacket类用来表示数据包。DatagramPacket类的构造方法如下
DatagramPacket(byte[] buf, int length)。 DatagramPacket(byte[] buf, int length, InetAddress address, int port)。 第一种构造方法在创建DatagramPacket对象时指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小还指定了数据包的目标地址和端口。在发
送数据时必须指定接收方的Socket地址和端口号因此使用第二种构造方法可创建发送数据的DatagramPacket对象。 2.DatagramSocket类 java.net包中的DatagramSocket类用于表示发送和接收数据包的套接字。该类的构造方法如下
DatagramSocket()。DatagramSocket(int port)。DatagramSocket(int port, InetAddress addr)。
第一种构造方法创建DatagramSocket对象构造数据报套接字并将其绑定到本地主机任何可用的端口上。第二种构造方法创建DatagramSocket对象创建数据报套接字并将其绑定到本地主机的指定端口上。第三种构造方法创建DatagramSocket对象创建数据报套接字并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个IP地址的情况。
如果接收数据时必须指定一个端口号不允许系统随机产生此时可以使用第二种构造方法。比如有个朋友要你给他写信那他的地址就必须确定不确定是不行的。在发送数据时通常使用第一种构造方法不指定端口号而是系统为我们分配一个端口号就像寄信不需要到指定的邮局去寄一样。
3.UDP网络程序设计
根据前面所讲的网络编程的基本知识以及UDP网络编程的特点下面创建一个广播数据报程序。广播数据报是一项较新的技术其原理类似于电台广播。广播电台需要在指定的波段和频率上广播信息收听者也要将收音机调到指定的波段、频率才可以收听广播内容。
例题21.3:创建UDP协议广播电台程序
package wanluo;import java.io.IOException;
import java.net.*;public class Notification extends Thread{String weather 节日预报八点有大型晚会请收听;//发送的消息int port 9898;//端口InetAddress iaddress null;MulticastSocket socket null;//多点广播套接字SuppressWarnings(deprecation)Notification(){try {iaddress InetAddress.getByName(224.255.10.0);//广播组地址socket new MulticastSocket(port);//实例化多点广播套接字socket.setTimeToLive(1);//指定发送范围是本地网络socket.joinGroup(iaddress);//加入广播组}catch(IOException e) {e.printStackTrace();//输出异常信息}}public void run() {while(true) {DatagramPacket packet null;//数据包byte data[] weather.getBytes();//字符串消息的字节数组packet new DatagramPacket(data,data.length,iaddress,port);//将数据打包System.out.println(weather);//控制台打印消息try {socket.send(packet);//发送数据sleep(3000);//线程休眠}catch(IOException e){e.printStackTrace();}catch(InterruptedException e){e.printStackTrace();}}}public static void main(String[] args) {Notification w new Notification();w.start();//启动线程}
}接收广播程序。单击“开始接收”按钮系统开始接收主机播出的信息单击“停止接收”按钮系统停止接收广播主机播出的信息。代码如下
package wanluo;import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.*;
import javax.swing.*;public class Receive extends JFrame implements Runnable,ActionListener{int port;//端口InetAddress group null;//广播组地址MulticastSocket socket null;//多点广播套接字对象JButton inceBtn new JButton(开始接收);JButton stopBtn new JButton(停止接收);JTextArea inceAr new JTextArea(10,10);//显示接收广播的文本域JTextArea inced new JTextArea(10,10);Thread thread;boolean stop false;//停止接收信息状态public Receive() {setTitle(广播数据报);setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);thread new Thread(this);inceBtn.addActionListener(this);//绑定按钮ince的单击事件stopBtn.addActionListener(this);//绑定按钮stop的单击事件inceAr.setForeground(Color.blue);//指定文本域中文字的颜色JPanel north new JPanel();north.add(inceBtn);//将按钮添加到面板north上north.add(stopBtn);add(north,BorderLayout.NORTH);//将north放置在窗体的上部JPanel center new JPanel();//创建面板对象centercenter.setLayout(new GridLayout(1,2));//设置面板布局center.add(inceAr);//将文本域添加到面板上center.add(inced);add(center,BorderLayout.CENTER);//设置面板布局validate();//刷新port 9898;//设置端口号try {group InetAddress.getByName(224.255.10.0);//指定接收地址socket new MulticastSocket(port);//绑定多点广播套接字socket.joinGroup(group);//加入广播组}catch(IOException e){e.printStackTrace();//输出异常信息}setBounds(100,50,360,380);//设置布局setVisible(true);//将窗体设置为显示状态}public void run() {//run()方法while(!stop) {byte data[] new byte[1024];//创建缓存字节数组DatagramPacket packet null;packet new DatagramPacket(data,data.length,group,port);//待接收的数据包try {socket.receive(packet);//接收数据包String message new String(packet.getData(),0,packet.getLength());inceAr.setText(正在接收的内容\n message);//将接收内容显示在文本域中inceAr.append(message \n);//每条信息为一行}catch(IOException e){e.printStackTrace();//输出异常信息}}}public void actionPerformed(ActionEvent e) {//单击按钮ince触发的事件if(e.getSource() inceBtn) {inceBtn.setBackground(Color.red);//设置按钮颜色stopBtn.setBackground(Color.yellow);if(!(thread.isAlive())) {//如线程不处于新建状态thread new Thread(this);//实例化Thread对象}thread.start();//启动线程stop false;//开始接收信息}if(e.getSource() stopBtn) {//单击按钮stop触发的事件inceBtn.setBackground(Color.yellow);//设置按钮颜色inceBtn.setBackground(Color.red);stop true;//停止接收信息}}public static void main(String[] args) {Receive rec new Receive();rec.setSize(460,200);}}结果如下 说明
发出广播和接收广播的主机地址必须位于同一个组内地址范围为224.0.0.0224.255.255.255该地址并不代表某个特定主机的位置。加入同一个组的主机可以在某个端口上广播信息也可以在某个端口上接收信息。