学习概述:学习计算机网络的基础知识,(TCP,UDP)两个方面的网络编程,以及为网络编程增加多线程
学习目标:1.掌握计算机网络基础知识(两大网络模型,IP协议,URL)
2.掌握TCP,UDP协议下的网络编程,并且特别注意是多线程并发情况下的Socket编程
3.学会使用Socket编写基础的聊天程序,文件上传程序
1.计算机网络基础
<1>目前计算机网络模型包括TCP/IP和OSI两大模型,分别如下所示
【1】各个层次中的主要协议
<2> IP地址和端口号
IP地址用于标志网络中的一个通信实体,这个通信实体可以是一个主机,也可以是一台打印机,或者是路由器的某一个端口。而在基于IP协议网络中传输的数据包,都必须用IP地址来标识。IP地址用来标识确定网络上的一个通信实体。
端口是一个16位的整数,用于表示数据交给哪个通信程序处理。因此,端口就是应用程序与外界交流的出入口。
不同的应用程序处理不同端口上的数据,同一个机器上不能有两个程序使用同一个端口,端口号可以从0到65535。
我们可以打个这样的比喻:IP地址是一个门牌号,那么端口就是房号。
2.基于TCP协议的网络编程
TCP是一种的可靠的网络协议,他在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。Java对于基于TCP协议的网络通信提供了良好了封装,Java使用的Socket对象代表两端的通信端口,并通过Socket产生IO流进行网络通信。
TCP网络编程步骤如下
【1】使用ServerSocket创建TCP服务器端
【2】客户端创建一个Socket进行通信
展示一个加入多线程操作的基于TCP协议的通信程序
package com.lee.QQ2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
Socket s = new Socket("127.0.0.1",30003);
PrintStream ps =new PrintStream(s.getOutputStream());
new Thread(new ClientThread(s)).start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null){
ps.println(s.getInetAddress()+" " + line);
}
}
}
package com.lee.QQ2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientThread implements Runnable {
private Socket s;
BufferedReader br = null;
public ClientThread(Socket s) {
super();
this.s = s;
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
String content =null;
try {
while((content=br.readLine())!=null){
System.out.println(content);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.lee.QQ2;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
public static List<Socket> socketList = new ArrayList<Socket>();
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(30003);
while(true){
Socket s = ss.accept();
socketList.add(s);
new Thread(new ServerThread(s)).start();
}
}
}
package com.lee.QQ2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class ServerThread implements Runnable {
Socket s= null;
BufferedReader br=null;
public ServerThread(Socket s) throws IOException {
super();
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run(){
String content =null;
try {
while((content=br.readLine())!=null){
for(Socket s :Server.socketList){
PrintStream ps =new PrintStream(s.getOutputStream());
ps.println(content);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
对于Java网络编程,由于Java应帮我们封装的很好,实际上记住步骤和一些关键方法,具体编写程序的时候去查API。
2.基于UDP协议的网络编程
UDP协议是一种不可靠协议,他在通信实例的两端各建立一个Socket,但两个Socket之间并没有虚拟链路,这两个Socket只是发送接收数据包的对象,Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket发送,接收数据包。我么可以这么比喻:Socket作为码头,DatagramPacket是船只。
UDP与TCP的协议简单对比如下:
【1】TCP协议:可靠,传输大小无限制,但是需要先建立连接
【2】UDP协议:不可靠,差错控制开销比较小,传输大小限制在64K一下,不需要建立连接
下面是一个简单的UDP协议下的网络编程例子程序:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Socket;
import java.util.Scanner;
public class UdpDemo {
public static void main(String[] args){
UdpDemo udp = new UdpDemo();
UdpClient client = udp.new UdpClient();
UdpServer server = udp.new UdpServer();
server.init();
client.init();
}
class UdpServer{
public static final int PORT =30000;
private byte[] buff = new byte[4096];
private DatagramPacket outPacket =null;
private DatagramPacket inPacket = new DatagramPacket(buff, buff.length);
private DatagramSocket socket=null;
Scanner sc =new Scanner(System.in);
String str =sc.next();
byte[] out = str.getBytes();
public void init(){
try{
socket = new DatagramSocket(PORT);
socket.receive(inPacket);
String ip = inPacket.getAddress().getHostName();
System.out.println(ip + new String(buff,0,inPacket.getLength()));
outPacket = new DatagramPacket(out, out.length,inPacket.getSocketAddress());
socket.send(outPacket);
}
catch(IOException e){
e.printStackTrace();
}
finally{
if(socket!=null){
socket.close();
}
}
}
}
class UdpClient{
public static final int DESC_PORT=30000;
public static final String IP="127.0.0.1";
private byte[] buff = new byte[4096];
private DatagramPacket outPacket =null;
private DatagramPacket inPacket = new DatagramPacket(buff, buff.length);
private DatagramSocket socket=null;
Scanner sc =new Scanner(System.in);
String str =sc.next();
byte[] out = str.getBytes();
public void init(){
try{
socket = new DatagramSocket(DESC_PORT);
socket.receive(inPacket);
System.out.println(new String(buff,0,inPacket.getLength()));
outPacket = new DatagramPacket(out, out.length,inPacket.getSocketAddress());
socket.send(outPacket);
}
catch(IOException e){
e.printStackTrace();
}
finally{
if(socket!=null){
socket.close();
}
}
}
}
}
3.URL
URL对象代表统一资源定位符,她是指向互联网资源的指针,资源可以是简单的文件盒和目录,也可以是更加复杂的对象引用。通常情况下:URL有以下几个部分组成
协议名,主机,端口和资源,例如:http:\\www.oneed.cn\Index
学习总结:
这一部分中间介绍了Java网络编程方面的知识。包括计算机网络基础相关知识,本部分详细介绍了ServerSocket,Socket,DatagramSocket,DatagramPacket等类。程序可以通过这几个类分别实现TCP服务器,TCP客户端以及UDP服务器和客户端,并且通过编写局域网通信工具加深了对Java网络编程的认识。
学习要点:
1.Socket有两个方法getOutputStream和getInputStream,一定要搞清数据流的流向问题,输入流和输出流都是针对已经定义好的Socket而言的
2.要有处理异常的意识,网络编程这一块异常很频繁,对于几个常见异常像IOException,UnkonwnHostException要熟记在心,不能全部依靠编译器帮助你抛出异常。