黑马程序员——Java 网络编程

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


Java 网络编程


1.网络编程概述

 

1.计算机网络概述

是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

2.网络编程目的

就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

网络编程中有两个主要的问题:

  1.如何准确地定位网络上一台或多台主机。

  2.找到主机后如何可靠高效地进行数据传输。

目前较为流行的网络编程模型是客户端/服务器(C/S)结构。即通信双方一方作为服务器等待客户提出请求并予以相应。客户则在需要服务时向服务器提出申请。服务器始终运行,监听网络端口,一旦有客户请求,就会启动一个服务线程来响应该客户,同时自己继续监听服务窗口,使后来的客户也能及时得到服务。

3.IP地址

  IP网络中每台主机都必须有一个唯一的IP地址,IP地址是一个逻辑地址。英特网上的IP地址具有全球唯一性。计算机只能识别二进制的数据,所以IP地址是一个二进制数据。但是又为了方便表示IP地址,我们把IP地址的每一个字节上的数据换算成十进制,然后用.分开表示:”点分十进制”。32位,四个字节,常用点分十进制的格式表示。

 例如:192.168.1.100  –> 11000000 10101000 00000001  01100100

IP地址的组成:网络号段+主机号段

IP地址分类:五大类

A类       1.0.0.1---127.255.255.254

(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)

(2)127.X.X.X是保留地址,用做循环测试用的。

B类 128.0.0.1---191.255.255.254

172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。

C类 192.0.0.1---223.255.255.254       192.168.X.X是私有地址(生活中常用的网段)

D类       224.0.0.1---239.255.255.254   

E类 240.0.0.1---247.255.255.254

4.协议

为进行网络中的数据交换(通信)而建立的规则、标准或约定。(=语义+语法+规则)。

  不同层具有各自不同的协议。

5.网络模型

计算机网络之间以何种规则进行通信,就是网络模型研究问题。

网络模型一般是指 OSI(Open System Interconnection开放系统互连)参考模型、

TCP/IP参考模型。

TCP/IP与OSI参考模型的对应关系:



OSI参考模型包括七个层次:

应用层:处理网络应用

表示层:数据表示

会话层:主机间通信

传输层:端到端的连接

网络层:寻址和最短路径

数据链路层:介质访问(接入)

物理层:二进制传输

 

TCP/IP模型包括四个层次:

  应用层

  传输层

  网络层

  网络接口

 

OSI各层所使用的协议:

  应用层:Telnet、FTP、HTTP、DNS、SMTP、POP3

  传输层:TCP、UDP

  TCP:面向连接的可靠的传输协议。

  UDP:是无连接的,不可靠的传输协议。

  网络层:IP、ICMP、IGMP

 

通信实体的对等层之间不允许直接通信,各层之间是严格的单向依赖,上层(Service user)使用下层提供的服务,下层(Serviceprovider)向上层提供服务。对等层通信的实质:对等层实体之间虚拟通信,下层向上层提供服务,实际通信在最底层完成。

 

6.端口

在互联网上传输的数据都包含有用来识别目的地的IP地址和端口号。IP地址用来标识网络上的计算机,而端口号用来指明该计算机上的应用程序。端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。应用程序通过系统调用与某端口建立连接(binding)后,传输层传给该端口的数据都被相应的进程所接收,相应进程发给传输层的数据都通过该端口输出。端口用一个整数型标识符来表示,即端口号。端口号跟协议相关,TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立,端口通常称为协议端口(protocol port),简称端口。端口使用一个16位的数字来表示,它的范围是0~65535,1024以下的端口号保留给预定义的服务。例如,http使用80端口。

7.数据封装

  一台计算机要发送数据到另一台计算机,数据首先必须打包,打包的过程称为封装。封装就是在数据前面加上特定的协议头部。OSI参考模型中,对等层协议之间的交换的信息单元称为协议数据单元(PDU, Protocol Data Unit)。OSI参考模型中的每一层都要依靠下一层提供的服务。为了提供服务,下层把上层的PDU作为本层的数据封装,然后加入本层的头部(和尾部)。头部中含有完成数据传输所需的控制信息。这样,数据自上而下递交的过程实际上就是不断封装的过程。到达目的地后自下而上递交的过程就是不断拆封的过程。由此可知,在物理线路上传输的数据,其外面实际上被包封了多层“信封”。

 

8.TCP和UDP传输协议

 

1.TCP协议

  TCP是Transfer Control Protocol(传输控制协议)的简称,是一种面向连接的保证可靠传输的协议

  在TCP/IP协议中,IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一确定Internet上的一台主机。而TCP层则提供面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信。当一个socket(通常都是serversocket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。TCP是一个基于连接的协议,它能够提供两台计算机之间的可靠的数据流。HTTP、FTP、Telnet等应用都需要这种可靠的通信通道。

 

2.UDP协议

  UDP是User Datagram Protocol的简称,是一种无连接的协议。UDP是从一台计算机向另一台计算机发送称为数据报的独立数据包的协议,该协议并不保证数据报是否能正确地到达目的地,它是一个非面向连接的协议。每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达时间以及内容的正确性都是不能保证的。

 

3.TCP和UDP的区别

  1.使用UDP时,每个数据报中都给出了完整的地址信息,因此无需建立发送方和接收方的连接。

  2.对于TCP协议,由于它是一个面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中多了一个连接建立的时间。

  3.使用UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。

  4.TCP没有这方面的限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大量的数据。

 

总结:

       UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

  TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。

可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽。因此TCP传输的效率不如UDP高。TCP在网路通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。相比之下UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。

 

 

2.网络编程三要素

 

网络要进行通讯,需要哪些要素呢?

比如说:我要跟你说话.

第一个条件:我要先找到你 (IP)

第二个条件:你得有接收数据的地方——耳朵 (端口)

第三个条件:我跟你说话,你能接收到,咱按什么方式接收啊,我说英文你懂吗,说韩文你懂吗,不懂是吧,所以我还是说中文把.(协议)

 

IP地址:InetAddress网络中设备的标识,不易记忆,可用主机名。

端口号:用于标识进程的逻辑地址,不同进程的标识。

传输协议:通讯的规则。常见协议:TCP,UDP

 

要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。那么,我们如果获取和操作IP地址呢?为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress供我们使用。

InetAddress类

       InetAddress类没有明显的构造函数。为生成一个InetAddress对象,必须运用一个可用的工厂方法。工厂方法(factory method)仅是一个类中静态方法返回一个该类实例的约定。对于InetAddress,三个方法:getLocalHost()、getByName()以及getAllByName()可以用来创建InetAddress的实例。

  getLocalHost()仅返回象征本地主机的InetAddress对象。本机地址还为localhost,127.0.0.1,这三个地址都是一回事。

  getByName()方法返回一个传给它的主机名的InetAddress。如果这些方法不能解析主机名,它们引发一个UnknownHostException异常。

  在Internet上,用一个名称来代表多个机器是常有的事。getAllByName()工厂方法返回代表由一个特殊名称分解的所有地址的InetAddresses类数组。在不能把名称分解成至少一个地址时,它将引发一个UnknownHostException异常。

 

 

API

public class InetAddress extendsObject implementsSerializable

This class represents an Internet Protocol (IP) address.

public static InetAddress getByName(String host) throws UnknownHostException

在给定主机名的情况下确定主机的 IP 地址.主机名可以是机器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式.如果提供字面值 IP地址,则仅检查地址格式的有效性.


//InetAddress byName = InetAddress.getByName("Louis-PC");//在给定主机名的情况下确定主机的 IP 地址
//主机名可以是机器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式
InetAddress byName = InetAddress.getByName("192.168.26.80");
// 获取主机的IP地址和主机名
String hostName = byName.getHostName();
String ip = byName.getHostAddress();
System.err.println(hostName+"--"+ip);

JDK中的网络类

  通过java.net包中的类,java程序能够使用TCP或UDP协议在互联网上进行通讯。

  Java通过扩展已有的流式输入/输出接口和增加在网络上建立输入/输出对象特性这两个方法支持TCP/IP。

  Java支持TCP和UDP协议族。

  TCP用于网络的可靠的流式输入/输出。

  UDP支持更简单的、快速的、点对点的数据报模式。

1.创建和使用URL访问网络上的资源

  URL(Uniform Resource Locator)是统一资源定位符的简称,它表示Internet上某一资源的地址。

  通过URL我们可以访问Internet上的各种网络资源,比如最常见的WWW, FTP站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。

  在目前使用最为广泛的TCP/IP中对于URL中主机名的解析也是协议的一个标准,即所谓的域名解析服务。

  使用URL进行网络编程,不需要对协议本身有太多的了解,功能也比较弱,相对而言是比较简单的。

2.URL组成

  一个URL包括两个主要部分:

  协议标识符:HTTP, FTP, File等。

  资源名字:主机名,文件名,端口号,引用。

3.创建URL

  在Java程序中,可以创建表示URL地址的URL对象。

  URL对象表示一个绝对的URL地址,但URL对象可用绝对URL、相对URL和部分URL构建。

 

//创建URL的代码如下,如果创建失败会抛出异常
try{
	URL myURL = new URL("http://www.baidu.com/");
}catch (MalformedURLException e){
	//exception handler code here
}

获取URL对象属性

try {
	URL myURL = new URL("http://java.sun.com:80/docs/books/tutorial/index.html#DOWN");
	// 获取URL对象属性
	String protocal = myURL.getProtocol();
	String host = myURL.getHost();
	String file = myURL.getFile();
	int port = myURL.getPort();
	String ref = myURL.getRef();

	System.out.println(protocal + ", " + host + ", " + file + ", "+ port + ", " + ref);
} catch (MalformedURLException e) {
	// exception handler code here
}

使用URL访问网上资源:为获得URL的实际比特或内容信息,用它的openConnection()方法从它创建一个URLConnection对象,与调用URL对象相关,它返回一个URLConnection对象。它可能引发IOException异常。

URLConnection是访问远程资源属性的一般用途的类。如果你建立了与远程服务器之间的连接,你可以在传输它到本地之前用URLConnection来检查远程对象的属性。这些属性由HTTP协议规范定义并且仅对用HTTP协议的URL对象有意义。URL和URLConnection类对于希望建立与HTTP服务器的连接来获取信息的简单程序来说是非常好的。

1.建立连接,从连接对象获取输入流,然后读入,再写出到文件中去.

URL url = new URL("http://www.baidu.com/");
// 打开连接
URLConnection conn = url.openConnection();
// 得到输入流
InputStream is = conn.getInputStream();
// 关于IO流的用法和写法一定要熟悉
OutputStream os = new FileOutputStream("d:\\baidu.txt");
byte[] buffer = new byte[2048];
int length = 0;
while (-1 != (length = is.read(buffer, 0, buffer.length))){
    os.write(buffer, 0, length);
}
is.close();
os.close();

2. 也可以直接从URL对象获取输入流.

URL url = new URL("http://www.baidu.com/");
// 另一种得到输入流的方法:通过url直接获取
InputStream is = url.openStream();
// 关于IO流的用法和写法一定要熟悉
OutputStream os = new FileOutputStream("d:\\baidu.txt");
byte[] buffer = new byte[2048];
int length = 0;

while (-1 != (length = is.read(buffer, 0, buffer.length))){
	os.write(buffer, 0, length);
}
is.close();
os.close();

其实上面两种方式的实现机制是一样的.

public final InputStream openStream() throws java.io.IOException {
	return openConnection().getInputStream();
}

示例:用字符流的方式读取网站内容显示在控制台上。

URL url = new URL("http://www.baidu.com/");
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String line = null;
while (null != (line = br.readLine())){
    System.out.println(line);
}
br.close();

3.TCP编程


使用TCP/IP的套接字(Socket)进行通信

1.套接字Socket的引入

为了能够方便地开发网络应用软件,由美国伯克利大学在Unix上推出了一种应用程序访问通信协议的操作系统用调用socket(套接字)。socket的出现,使程序员可以很方便地访问TCP/IP,从而开发各种网络应用的程序。随着Unix的应用推广,套接字在编写网络软件中得到了极大的普及。后来,套接字又被引进了Windows等操作系统中。Java语言也引入了套接字编程模型。

2. 什么是Socket?

  Socket是连接运行在网络上的两个程序间的双向通讯的端点。通俗的说就是网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

3. Socket原理机制

服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户的连接请求。客户程序根据服务器程序所在的主机名和端口号发出连接请求。通信的两端都有Socket。网络通信其实就是Socket间的通信。数据在两个Socket间通过IO传输(有相应的协议支持)。




如果一切正常,服务器接受连接请求。并获得一个新的绑定到不同端口地址的套接字。(不可能有两个程序同时占用一个端口)。客户和服务器通过读写套接字进行通讯。



使用ServerSocket和Socket实现服务器端和客户端的Socket通信。




其中:左边ServerSocket类的构造方法可以传入一个端口值来构建对象。accept()方法监听向这个socket的连接并接收连接。它将会阻塞直到连接被建立好。连接建立好后它会返回一个Socket对象。连接建立好后,服务器端和客户端的输入流和输出流就互为彼此,即一端的输出流是另一端的输入流。

4.Socket示例演示

要点步骤:

使用ServerSocket和Socket实现服务器端和客户端的Socket通信:

(1)建立Socket连接

(2)获得输入/输出流

(3)监听客户端,返回socket对象

(4)读/写数据

(5)关闭 输入/输出流,Socket

示例1:测试两个简单的socket连接。先运行服务器端,再运行客户端,可以看到,运行客户端之后输出服务器端的后续代码。表明连接建立后才会往下执行。

TcpClient客户端程序

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {
	public static void main(String[] args){
		try {
			// 建立客户的Socket
			new Socket("127.0.0.1",5000);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

TcpServer服务端程序

import java.io.IOException;
import java.net.ServerSocket;

/*
 * 通信程序测试
 */
public class TcpServer {

	public static void main(String[] args) {
		try {
			new ServerSocket(5000).accept();
		} catch (IOException e) {
			e.printStackTrace();
			System.err.println("连接失败..");
		}
		System.err.println("连接成功..");
	}
}

示例2:测试两个socket之间的简单通信。

TcpServer服务端


package cn.itcast.demo2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 测试:两个socket之间的简单通信
*/
public class TcpServer {

	public static void main(String[] args) {
		// 创建服务端的socket对象,指定端口
		ServerSocket ss;
		try {
			ss = new ServerSocket(5000);
			// 开始监听连接,返回socket对象
			Socket socket = ss.accept();
			System.err.println("连接成功..");
			//获得服务器端的输入流,从客户端接收消息
			InputStream is = socket.getInputStream();
			// 服务器端的输出流,向客户端发送消息
			OutputStream os = socket.getOutputStream();
			
			os.write("serverSocket output message..".getBytes());
			
			byte[] buffer = new byte[1024];
			int length = 0;
			length = is.read(buffer);
			String str = new String(buffer, 0, length);
			System.err.println(str);
			is.close();
			os.close();
			ss.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.err.println("连接失败..");
		}
		
	}
}

TcpClient客户端

package cn.itcast.demo2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {

	public static void main(String[] args) {
		try {
			//建立socket并指定端口
			Socket socket = new Socket("127.0.0.1",5000);
			//客户端的输出流
			OutputStream os = socket.getOutputStream();
			//将信息写入流,把这个信息发送到服务器
			os.write("Hello serverSocket".getBytes());
			
			//从服务器接收信息并输出
			InputStream is = socket.getInputStream();
			byte[] buffer = new byte[1024];
			int length = is.read(buffer);
			String str = new String(buffer,0,length);
			System.err.println(str);
			
			// 关闭资源
			is.close();
			os.close();
			socket.close();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

程序运行输出:

连接成功..

Hello serverSocket

--------------------

serverSocket output message..

 

5.使用线程实现服务器端与客户端的双向通信

代码实现:MainServer类, ServerInputThread线程类, ServerOutputThread线程类

MainClient类,ClientInputThread线程类,ClientOutputThread线程类

MainServer类


import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 使用线程实现服务器端与客户端的双向通信:
 *  MainServer服务端主程序
 */
public class MainServer {
	public static void main(String[] args) {
		try {
			ServerSocket ss = new ServerSocket(5000);
			while(true){
				//监听状态
				Socket socket = ss.accept();
				//启动读写线程
				new ServerInputThread(socket).start();
				new ServerOutputThread(socket).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

ServerInputThread线程类

public void run() {
	try {
		//获得输入流
		InputStream is = socket.getInputStream();
		while(true){
			byte[] buf = new byte[1024];
			int length = is.read(buf);
			System.err.println("from client: "+new String(buf,0,length));
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

ServerOutputThread线程类


public void run() {
	try {
		//输出流
		OutputStream os = socket.getOutputStream();
		while(true){ // 键盘录入数据
			BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
			String line = reader.readLine();
			os.write(line.getBytes());
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

 

MainClient类

public class MainClient {
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("127.0.0.1",5000);
		new ClientInputThread(socket).start();
		new ClientOutputThread(socket).start();
	}
}

ClientInputThread线程类


public void run() {
	try {
		InputStream is = socket.getInputStream();
		while(true){
			byte[] buf = new byte[1024];
			int length = is.read(buf);
			System.err.println("from server: "+new String(buf,0,length));
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

ClientOutputThread线程类

public void run() {
	try {
		OutputStream os = socket.getOutputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String line = reader.readLine();
		os.write(line.getBytes());
	} catch (IOException e) {
		e.printStackTrace();
	}
}

经测试成功。即从服务器端控制台输入,可以从客户端接收到并输出;也可以反过来,从客户端控制台输入,那么服务器端会同时输出。

 

测试多个客户端模式:经实验,发现在一个服务器多个客户端的情况下,客户端可以流畅地向服务器发送信息,但是当服务器发送信息时,就会出现问题,并不是每一个客户端都能收到信息。如图中,当服务器发送语句时,第一个客户端收到了(并且是发送后多按下一个回车才收到),第二个客户端没有收到。




 

 

4.UDP编程


1.使用无连接的数据报(UDP)进行通信

什么是Datagram?

数据报是网上传输的独立数据包,数据报是否能正确地到达目的地,到达的时间,顺序,内容的正确性均没有保障。

Java中使用Datagram与DatagramPacket类。DatagramSocket类利用UDP协议来实现客户与服务器的Socket。

可以用写信寄信的例子来类比UDP通信。此时DatagramPacket就相当于一个包装了信封的信件。填好地址和接收人之后,就可以寄出去。

简单的UDP通讯示例程序:

UDPReceiveDemo接收数据端

package cn.itcast_03;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * UDP传输协议接收数据:
 * 1.创建接收端socket对象
 * 2.创建一个数据包(接收容器)
 * 3.调用Socket对象的接收方法接收数据包
 * 4.解析数据包
 * 5.释放资源
 * 
 * 接收消息的同时给发送端发送信息
 */

public class UDPReceiveDemo {
	public static void main(String[] args) throws IOException {
		// 创建接收端Socket对象
		DatagramSocket ds = new DatagramSocket(5000);
		// 创建一个数据包(接收容器)
		byte[] buf = new byte[1024];//数据小
		int length = buf.length;
		DatagramPacket dp = new DatagramPacket(buf,length);
		//接收到数据包,(IP,hostName....)
		ds.receive(dp);
		//解析数据,并输出
		InetAddress address = dp.getAddress();
		String IP = address.getHostAddress();
		String hostName = address.getHostName();
		System.err.println(hostName+"--"+IP);
		// 获取数据缓冲区以及长度
		byte[] data = dp.getData();
		int len = dp.getLength();
		String str = new String(data,0,len);
		System.err.println(str);
		// 返回信息
		String ok = "I am ok!";
		DatagramPacket rePackageData = new DatagramPacket(ok.getBytes(), ok.length(),address,dp.getPort());
		ds.send(rePackageData);
		
		ds.close();
	}
}
UDPSendDemo发送数据端
package cn.itcast_03;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * UDP传输协议发送数据:
 * 1.创建发送端socket对象
 * 2.创建数据,并把数据打包
 * 3.调用Socket对象的发送方法发送数据包
 * 4.释放资源
 * 
 * 发送消息的同时还可以接收对方的信息
 */
public class UDPSendDemo {

	public static void main(String[] args) throws IOException {
		// 创建DatagramSocket发送端的socket对象
		DatagramSocket ds = new DatagramSocket();
		// 准备数据打包--DatagramPacket
		// public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
		byte[] buf = "Hello UDP , Welcome!!".getBytes();
		int length = buf.length;
		InetAddress address = InetAddress.getByName("Louis-PC");
		DatagramPacket dataPacket = new DatagramPacket(buf, length, address, 5000);
		// 发送数据包
		ds.send(dataPacket);
		//还可以接收对方的信息
		byte[] buffer = new byte[1024];
		DatagramPacket p = new DatagramPacket(buffer, 100);
		ds.receive(p);
		//p.getLength():the length of the data to be sent or the length of the data received
		System.err.println(new String(buffer, 0, p.getLength()));
		//释放资源
		ds.close();
	}
}

2.UDP实现简单的多人聊天程序

ChatRoom主程序

package cn.itcast_06;

import java.net.DatagramSocket;
import java.net.SocketException;
/**
 * UDP实现简单的多人聊天程序
 */
public class ChatRoom {

	public static void main(String[] args) throws SocketException {
		//发送和接收数据报包的套接字 a socket for sending and receiving datagram packets
		DatagramSocket dsSend = new DatagramSocket();
		DatagramSocket dsReceive = new DatagramSocket(12306);
		
		SendThread st = new SendThread(dsSend);
		ReceiveThread rt = new ReceiveThread(dsReceive);
		
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(rt);
		
		t1.start();
		t2.start();
	}
}

SendThread线程类

package cn.itcast_06;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendThread implements Runnable {
	
	private DatagramSocket dsSend;
	public SendThread(DatagramSocket dsSend) {
		this.dsSend = dsSend;
	}
	@Override
	public void run() {
		try{
			// 准备从键盘录入数据
			BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
			String line = null;
			while(null != (line = reader.readLine())){
				if("bye".equals(line)){
					break;
				}
				byte[] buf = line.getBytes();
				DatagramPacket dataPacket = new DatagramPacket(buf, buf.length, InetAddress.getByName("Louis-PC"), 12306);
				// 发送数据包
				dsSend.send(dataPacket);
			}
			//释放资源
			dsSend.close();
		}catch(IOException e){
			e.printStackTrace();
		}
	}
}

ReceiveThread线程类

package cn.itcast_06;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveThread implements Runnable {
	private DatagramSocket dsReceive;
	public ReceiveThread(DatagramSocket dsReceive) {
		this.dsReceive = dsReceive;
	}
	@Override
	public void run() {
		try {
			while(true){
				byte[] buf = new byte[1024];//数据小
				DatagramPacket dp = new DatagramPacket(buf,buf.length);
				//接收到数据包
				dsReceive.receive(dp);
				//解析数据,并输出
				String ip = dp.getAddress().getHostAddress();
				String str = new String(dp.getData(),0,dp.getLength());
				System.err.println("From "+ ip +" data is : "+ str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



总结:网络编程

       (1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享

       (2)网络编程模型

       (3)网络编程的三要素

              A:IP地址

                     a:点分十进制

                     b:IP地址的组成

                     c:IP地址的分类

                     d:dos命令

                     e:InetAddress

              B:端口

                     是应用程序的标识。范围:0-65535。其中0-1024不建议使用。

              C:协议

                     UDP:数据打包,有限制,不连接,效率高,不可靠

                     TCP:建立数据通道,无限制,效率低,可靠

       (3)Socket机制

              A:通信两端都应该有Socket对象

              B:所有的通信都是通过Socket间的IO进行操作的

       (4)UDP协议发送和接收数据

              发送:

                     创建UDP发送端的Socket对象

                     创建数据并把数据打包

                     发送数据

                     释放资源

                    

              接收:

                     创建UDP接收端的Socket对象

                     创建数据包用于接收数据

                     接收数据

                     解析数据包

                     释放资源

       (5)TCP协议发送和接收数据

              发送:

                     创建TCP客户端的Socket对象

                     获取输出流,写数据

                     释放资源

                    

              接收:

                     创建TCP服务器端的Socket对象

                     监听客户端连接

                     获取输入流,读取数据

                     释放资源

       (6)案例:

              A:UDP

                     a:最基本的UDP协议发送和接收数据

                     b:把发送数据改进为键盘录入

                     c:一个简易聊天小程序并用多线程改进

              B:TCP

                     a:最基本的TCP协议发送和接收数据

                     b:服务器给出反馈

                     c:客户端键盘录入服务器控制台输出

                     d:客户端键盘录入服务器写到文本文件

                     e:客户端读取文本文件服务器控制台输出

                     f:客户端读取文本文件服务器写到文本文件

                     g:上传图片

                     h:多线程改进上传文件








------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值