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

14--黑马程序员--技术总结之网络编程

2015-05-11 13:37 399 查看
----------------------ASP.Net+Unity开发.Net培训、期待与您交流!
----------------------

一.网络编程的概念介绍

1.网络编程的定义
网络编程从大的方面说就是对信息的发送到接收,中间传输为物理线路的作用,编程人员可以不用考虑……

网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的!中间最主要的就是数据包的组装,数据包的过滤,数据包的捕获,数据包的分析,当然最后再做一些处理!

代码,开发工具,数据库,服务器架设和网页设计这5部分你都要接触

2.网络模型
网络模型:描述网络的结构原理和工作原理

OSI参考模型:七层

Internet网络模型(TCP/IP模型):四层

OSI模型和TCP/IP模型的示意图及对应关系如下图所示:



网络协议:指定层上进行数据交换的规则。

Internet的网络层协议:IP协议;DNS协议(辅助协议)

Internet的传输层协议:TCP协议;UDP协议。TCP协议特点:

1)在传输数据前需要建立连接,通过三次握手完成,tcp通信是面向连接的。

2)数据在传输过程中不需要大包操作,可以传输大量的数据。

3)由于是在建立连接的基础上进行数据的传输,该协议比较可靠。

4)想传数据,必须建立连接,在速度和效率上稍低。

UDP协议的特点:

1)UDP是面向无连接的,双方进行通信不需要建立连接。

2)数据在传输过程中要进行打包操作,每个包的最大为64K字节。

3)面向无连接的传输,该协议不可靠。

4)不需要建立连接,传输速度快,效率高。

3.套接字

套接字(Sockets):应用程序和网络协议的接口。

Java Sockets:Java应用程序和网络协议的接口,提供若干个类的定义。

Java应用程序利用这些类继承网络协议的行为,实现网络通信。

TCP Sockets:使用TCP协议实现可靠的网络通信。

UDP Sockets:使用UDP协议实现效率较高的网络通信。

4.数据包

数据包是网络通信编程的一个重要概念,也称为组装包,指在应用层数据或报文按照一定事先规定好的规则整合的数据集合,实际操作包括组包(打包),数据包传送,解包。 组包(打包),指按照协议把零散的数据或报文按照组合起来,实际应用中,比如在C++编程中,往往定义一种新的数据类型用来存储数据包的结构。数据包传送,指数据包的电气物理传输。解包,指接收端对接收的数据进行解析,获得有用信息和数据。

数据包经常通过套接字来传送.

5.两台计算机的通信机制。

两台互相联立的计算机,进行通信是需要借助于网络设备的同时,计算机内部是怎么处理的呢?感觉我自己的认识概述如下。一台计算机想要通信首先要找到目标机,只要找到对象才有可能实现通信,这就引出了IP的概念,通信的计算机之间是通过IP地址来查找相应的目标计算机的。IP地址分为两种:IPV4和IPV6。IPV4是有四个字符数据组成,IPV6是有六个字符数据组成。每个字符数据的最大值是255。两台计算机通过网线连接一起后,在遵守TCP/IP协议的前提下,通过IP地址进行通信。每台计算机又有很多的应用程序,如果一台计算机发送数据到另一个计算机上,具体是哪一个应用程序接收呢?这个就需要有端口来区别。计算机一共分配了0--65535个数据用来表示端口。每一个应用程序都有一个自己的端口,也就是一个整数,通过这个端口来决定传输数据的时候具体发送到那一个应用程序上。所以说,计算机想要通信,首先要符合一定的协议,然后有一个IP地址,通过端口号来区分具体的应用程序来处理数据。

二.Java中网络编程类

java中用来网络编程的包是:java.net;

1.UDP协议

UDP协议通信使用的是java包中的DatagramSocket和DatagramPacket对象。建立通信机制的步骤是:

1)通过DatagramSocket对象是为网络通信构建一个通道,专业的叫法就是创建端口。

发送端具体实现代码:DatagramSocket ds = new DatagramSocket();

如果是发送端的话,这个端口可以不进行绑定,使用内核自由分配的端口号即可。如果是接受端的话,这个端口要必须要绑定到特定的端口,这个端口也可以叫做监视器。监视某个端口信息的变化。接收端具体实现代码:DatagramSocket ds = new DatagramSocket(端口号); 参看GDK手册有详细说明。

2)封包操作。

如果是发送端的话,首先要有数据,由于网络传输的都是二进制数据,所以在定义网络包的时候也要定义成二进制形式的。具体定义代码如下:

发送数据包数据:byte[] buf = "数据".getBytes();

接受数据包数据:byte[] buf = new byte[1024];

有了数据和数据缓冲区后,可以把这个数据和数据缓冲区封装成网络包:

发送端的数据包:DatagramPacket dp =

new DatagramPacket(buf,buf.length,InetAddress.getAddress("192.168.1.104"),10000);

接受端的数据包:DatagramPacket dp = new DatagramPacket(buf,buf.length);

3)发送接受操作。

根据端口Socket的方法,对数据包发送和接受操作。具体实现代码:

发送端:ds.send(dp);

接收端:ds.receive(dp); 接收到的数据包放到接收端定义的数据包缓冲区中。

4)关闭资源。

ds.close();

2.UDP方法介绍

类 DatagramSocket

此类表示用来发送和接收数据报包的套接字。

数据报套接字是包投递服务的发送或接收点。

每个在数据报套接字上发送或接收的包都是单独编址和路由的。

从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

在DatagramSocket上总是启用UDP广播发送。

为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。

在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。

构造方法:

DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可用的端口。

DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。

DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。

DatagramSocket(SocketAddress bindaddr) 创建数据报套接字,将其绑定到指定的本地套接字地址。

构造方法中的参数:

port - 要使用的端口。

laddr - 要绑定的本地地址

bindaddr - 要绑定的本地套接字地址,对于未绑定的套接字为 null。

方法:

close() 关闭此数据报套接字。

getPort() 返回此套接字的端口。

isBound() 返回套接字的绑定状态。

isClosed() 返回是否关闭了套接字。

disconnect() 断开套接字的连接。

isConnected() 返回套接字的连接状态。

getLocalPort() 返回此套接字绑定的本地主机上的端口号。

getInetAddress() 返回此套接字连接的地址。

send(DatagramPacket p) 从此套接字发送数据报包

getLocalSocketAddress() 返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。

getRemoteSocketAddress() 返回此套接字连接的端点的地址,如果未连接则返回 null。

receive(DatagramPacket p) 从此套接字接收数据报包。

connect(SocketAddress addr) 将此套接字连接到远程套接字地址(IP 地址 + 端口号)。

connect(InetAddress address, int port) 将套接字连接到此套接字的远程地址。

类 DatagramPacket

此类表示数据报包。

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。

从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

构造方法:

DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。

DatagramPacket(byte[] buf, int offset, int length) 构造 DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量。

DatagramPacket(byte[] buf, int length, SocketAddress address) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

方法:

getPort(int) 返回某台远程主机的端口号。

getData(byte[] ) 返回数据缓冲区。

getLength(int) 返回将要发送或接收到的数据的长度。

getOffset(int ) 返回将要发送或接收到的数据的偏移量。

getAddress() 返回某台机器的IP地址。InetAddress

getSocketAddress() 获取要将此包发送到的或发出此数据报的远程主机的SocketAddress。

setData(byte[] b) 为此包设置数据缓冲区。

setLength(int len) 为此包设置长度。

setPort(int iport) 设置要将此数据报发往的远程主机上的端口号。

setAddress(InetAddress iaddr) 设置要将此数据报发往的那台机器的IP 地址。

代码示例:

[html] view
plaincopy





public class UDPServer {

/**UDP服务器的创建

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try {

DatagramSocket server = new DatagramSocket(5050); //通过DatagramSocket对象是为网络通信创建端口

byte[] recvBuf = new byte[100];

DatagramPacket recvPacket = new DatagramPacket(recvBuf , recvBuf.length);

server.receive(recvPacket);

String recvStr = new String(recvPacket.getData() , 0 , recvPacket.getLength());

System.out.println("Hello World!" + recvStr);

int port = recvPacket.getPort();

InetAddress addr = recvPacket.getAddress();

String sendStr = "Hello ! I'm Server"; //发送给客户端的内容

byte[] sendBuf; //接受数据包数据

sendBuf = sendStr.getBytes(); //发送数据包数据

DatagramPacket sendPacket = new DatagramPacket(sendBuf , sendBuf.length , addr , port );

server.send(sendPacket);

server.close(); //关闭服务

}

catch (IOException e) {

System.out.println("服务器出错!");

}

}

}

[html] view
plaincopy





public class UDPClient {

/**UDP客户端的创建

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try {

DatagramSocket client = new DatagramSocket(); //创建端口

String sendStr = "Hello! I'm Client";

byte[] sendBuf;

sendBuf = sendStr.getBytes();

InetAddress addr = InetAddress.getByName("127.0.0.1"); //返回此套接字连接的地址

int port = 5050;

DatagramPacket sendPacket = new DatagramPacket(sendBuf ,sendBuf.length , addr , port);

client.send(sendPacket);

byte[] recvBuf = new byte[100]; //接受数据包数据

DatagramPacket recvPacket = new DatagramPacket(recvBuf , recvBuf.length);

client.receive(recvPacket);

String recvStr = new String(recvPacket.getData() , 0 ,recvPacket.getLength());

System.out.println("收到:" + recvStr); //收到的数据包内容

client.close(); //关闭服务

}

catch(IOException e) {

System.out.println("客户端出错!"); //若发生异常 ,客户端发送的消息

}

}

}

输出结果:



说明客户端成功收到了服务器端传来的消息,数据传输成功。

3.TCP协议

TCP协议通信使用的是java包中的Socket和ServerSocket对象。TCP和UDP的区别在于,TCP是建立连接,UDP是不需要连接,TCP操作的是端口输入输出流对象,UDP操作的是DatagramPacket包。按照TCP通信时不需要建立包,直接获取输入输出流操作即可。通信机制的

步骤如下:

1)TCP通信首先也是要建立Socket端口。UDP中客户端和服务端都是使用的DatagramSocket创建对象的方法,创建通信端口。TCP建立端口时,客户端和服务端是使用不一样的类。具体操作代码如下:

客户端:Socket s = new Socket();

服务端:ServerSocket ss = new ServerSocket(监听端口);

2)建立连接操作。

通过服务端ServerSocket对象的accept方法获得端口连接,在获得请求端口信息后,建立连接。

3)获得输入输出流操作。

在客户端获得Socket的getOutputStream()方法,通过该方法,输出数据。在服务端通过获得Socket的getInputStream()方法,读取数据。

4)关闭流操作。

客户端:s.close();

服务端:s.close; ss.close();

4.TCP方法介绍

类 ServerSocket

服务器套接字

服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

服务器套接字的实际工作由 SocketImpl 类的实例执行。应用程序可以更改创建套接字实现的套接

字工厂来配置它自身,从而创建适合本地防火墙的套接字。

构造方法:

ServerSocket() 创建非绑定服务器套接字。

ServerSocket(int port) 创建绑定到特定端口的服务器套接字。

ServerSocket(int port, int backlog) 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。

ServerSocket(int port, int backlog, InetAddress bindAddr) 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。

构造方法参数:

port - 本地 TCP 端口

backlog - 侦听 backlog

bindAddr - 要将服务器绑定到的 InetAddress

方法:

void close() 关闭此套接字。

Socket accept() 侦听并接受到此套接字的连接。

boolean isBound() 返回ServerSocket的绑定状态。

boolean isClosed() 返回ServerSocket的关闭状态。

String toString() 作为String返回此套接字的实现地址和实现端口。

int getLocalPort() 返回此套接字在其上侦听的端口。

InetAddress getInetAddress() 返回此服务器套接字的本地地址。

SocketAddress getLocalSocketAddress( null) 返回此套接字绑定的端点的地址,如果尚未绑定则返回。

void bind(SocketAddress endpoint) 将ServerSocket绑定到特定地址(IP 地址和端口号)。

void bind(SocketAddress endpoint, int backlog) 将ServerSocket绑定到特定地址(IP 地址和端口号)。

方法中的参数:

endpoint - 要绑定的 IP 地址和端口号。

backlog - 侦听 backlog 长度。

类 Socket

此类实现客户端套接字(也可以就叫“套接字”)。

套接字是两台机器间通信的端点。 套接字的实际工作由 SocketImpl 类的实例执行。

应用程序通过更改创建套接字实现的套接字工厂可以配置它自身,以创建适合本地防火墙的套接字。

构造方法:

Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字

Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 创建一个套接字并将其连接到指定远程地址上的指定远程端口。

Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。

Socket(String host, int port, InetAddress localAddr, int localPort) 创建一个套接字并将其连接到指定远程主机上的指定远程端口

构造方法参数:

port - 端口号。

address - IP 地址。

localAddr - 要将套接字绑定到的本地地址

localPort - 要将套接字绑定到的本地端口

host - 主机名,或者为 null,表示回送地址。

方法:

void close() 关闭此套接字。

boolean isBound() 返回套接字的绑定状态。

boolean isClosed() 返回套接字的关闭状态。

String toString() 将此套接字转换为 String。

int getPort() 返回此套接字连接到的远程端口。

int getLocalPort() 返回此套接字绑定到的本地端口。

void shutdownOutput() 禁用此套接字的输出流。

InetAddress getInetAddress() 返回套接字连接的地址。

InputStream getInputStream() 返回此套接字的输入流。

OutputStream getOutputStream() 返回此套接字的输出流。

void connect(SocketAddress endpoint) 将此套接字连接到服务器。

代码示例:

[html] view
plaincopy





public class TCPClient {

/**TCP客户端的创建

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try {

Socket s = new Socket("127.0.0.1",10000);

OutputStream out = s.getOutputStream();

out.write("TCP收到了吗".getBytes());

InputStream in = s.getInputStream();//获取服务端发来的数据,获取字节输入流

byte[] buf = new byte[10];

int len = 0 ;

len = in.read(buf);

System.out.println(new String(buf,0,len));

s.close();

}

catch (IOException e) {

System.out.println("客户端出错!");

}

}

}

[html] view
plaincopy





public class TCPServer {

/**TCP服务器的创建

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try {

ServerSocket ss = new ServerSocket(10000);

Socket s = ss.accept();

InputStream in = s.getInputStream();

byte[] buf = new byte[10];

int len = 0 ;

len = in.read(buf);

System.out.println(new String(buf,0,len));

OutputStream out = s.getOutputStream(); //服务端发送消息给客户端,获取字节输出流

out.write("OK收到了".getBytes());

s.close();

ss.close();

}

catch (IOException e) {

System.out.println("服务器出错!");

}

}

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