您的位置:首页 > 理论基础 > 计算机网络

黑马程序员——Java基础之网络编程

2015-07-02 09:17 696 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

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

一、因特网

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

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

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

我们熟悉的因特网就是有无数的广域网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);

}

}


运行结果:

发送端:



接收端:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: