java 网络编程(Socket) TCP/UDP 总结案例

时间:2021-02-13 10:21:04

网络编程:关注的是底层的数据传输

网页编程:数据的展示



1、基本概念


一、网络:将不同的计算机连接在一起局域网 城域网 互联网

二、地址:Ip地址确定网络上的绝对的地址位置   房子的地址

三、端口号(相当于房门):区分计算机上的软件 相当于房门两个字节0~65535 共65536个

1、 同一个协议下,端口号不能重复,不同的协议下可以重复

2、 1024以下的端口不要使用 80-->http 21-->ftp

四、资源定位 URL 统一资源定位 URI:统一资源

五、数据的传输

1、 协议:TCP UDP协议(重点的)

1)、TCP(transfer control protocol):必须先建立连接 先连接在通信 电话 类似于三次握手 面向连接 安全可靠 效率相对低下

 

2)、UDP(UserDatagramProtocol):类似于发短信 非面向连接 效率高


现在一般是将两者结合使用,底层一些不重要的数据使用UDP传输

2、 传输

1、 先封装

2、 后拆分

java 网络编程(Socket) TCP/UDP 总结案例


3、数据封装拆分


1、 InetAddress InetSocketAddress

2、 URL

3、 TCP:serverSocket(建立在服务器上)  Socket(建立在客户端上)

4、 UDP: DatagramSocket DatagramPacket

1、InetAddress:封装IP及DNS

方法:

getHostAddress() 返回ip地址

getHostName() 返回域名|本机为计算机名

InetAddress.getLocalHost();//本机

InetAddress.getByName(“IP地址|域名”);

2、InetSocketAddress:封装端口

1):创建对象:

InetSocketAddress(String hostname,int port)

InetSocketAddress(InetAddress addr,intport)

2):方法:

getAdddress()

getHostName()

getPort()

<span style="font-size:18px;">package com.net.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* 没有封装端口
* @author lyy
*
*/
public class InetDemo1 {

public static void main(String[] args) throws UnknownHostException {
//使用getLoaclHost方法创建InetAddress对象
InetAddress addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress());//返回ip地址
System.out.println(addr.getHostName());//输入计算机名
//根据域名得到InetAddress对象
addr = InetAddress.getByName("www.163.com");
System.out.println(addr.getHostAddress());//返回服务器的ip地址61.163.117.65
System.out.println(addr.getHostName()); //输出 www.163.com
//根据ip得到InetAddress对象
addr = InetAddress.getByName("61.163.117.65");//如果ip地址存在而且DNS帮你解析了,那么getHostName()这个方法返回的就是www.163.com ,否则输出Ip地址
System.out.println(addr.getHostAddress());//返回163的服务器的ip
System.out.println(addr.getHostName());//输入Ip而不是域名,如果这个Ip地址不存在


}
</span>
}



<span style="font-size:18px;">package com.net.ip;

import java.net.*;

/**
* 封装端口:在InetAddress基础上+端口
* @author lyy
*
*/
public class InetSocketDemo1 {

public static void main(String[] args) throws UnknownHostException {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
address= new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999);
System.out.println(address.getHostName());
System.out.println(address.getPort());
InetAddress addr = address.getAddress();
System.out.println(addr.getHostAddress());//返回ip地址
System.out.println(addr.getHostName());//输入计算机名


}

}</span>


3、网络爬虫原理

URI(Uniform resource identifier) 统一资源标识符,用唯一的标识一个资源

URL(Uniform resource Locator)统一资源定位器,他是一种具体的URI

四部分组成:协议存放资源的主机域名端口 资源文件名(/)

 URL:

一、创建

URI(String str)//绝对路径构建

URI(URL context,String spec)//相对路径构建

二、方法:

System.out.println("协议:"+url.getProtocol());

System.out.println("域名:"+url.getHost());

System.out.println("端口:"+url.getPort());

System.out.println("资源:"+url.getFile());

System.out.println("相对路径资源:"+url.getPath());

System.out.println("锚点:"+url.getRef());//锚点

System.out.println("参数:"+url.getQuery());//参数:存在锚点回返Null 如果不存在返回参数


<span style="font-size:18px;">package com.net.url;

import java.net.*;

public class URLDemo1 {
public static void main(String[] args) throws MalformedURLException {
//绝对路径构建
URL url = new URL("http://www.baidu.com:80/index.html#aa?uname=lyy");
System.out.println("协议:"+url.getProtocol());
System.out.println("域名:"+url.getHost());
System.out.println("端口:"+url.getPort());
System.out.println("资源:"+url.getFile());
System.out.println("相对路径资源:"+url.getPath());
System.out.println("锚点:"+url.getRef());//锚点
System.out.println("参数:"+url.getQuery());//参数 :存在锚点 返回Null 如果不存在返回参数





//相对路径构建
url = new URL("http://www.baidu.com:80/a/");
url = new URL(url,"b.txt");//相对路径
System.out.println(url.toString());
}
}<strong>
</strong></span>




4、通过流读取数据——OpenStream()


package com.net.url;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.*;

/**
* 获取资源:源代码
* @author lyy
*
*/
public class URLDemo2 {

public static void main(String[] args) throws IOException {
URL url = new URL("http://www.baidu.com/");//主页默认资源

//获取资源 网络流
//InputStream is = url.openStream();
//byte[] flush = new byte[1024];
//int len = 0;
//while(-1 != (len = is.read(flush))){
//System.out.println(new String(flush,0,len));
//}
//is.close();

BufferedReader br =
new BufferedReader(new InputStreamReader(url.openStream(),"utf-8"));
BufferedWriter bw =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html"),"utf-8"));

String msg = null;
while((msg = br.readLine()) != null){
bw.append(msg);
bw.newLine();

}
bw.flush();
br.close();
bw.close();
}

}


5、UDP通信

UDP:以数据为中心 非面向连接 不安全 数据可能丢失 效率高

一、类 DatagramSocketDatagramPacket

1、 客户端:

1)、创建客户端DatagramSocket 类 +指定端口

2)、准备数据字节数组

3)、打包 datagramPacket  + 服务器地址和端口

4)、发送

5)、释放资源

 

2、 服务端

a)      创建服务端 DatagramSocket类 +指定端口

b)      准备接收的容器字节数组 封装datagramPacket 

c)       包接收数据

d)      分析数据

e)      释放资源

 

典型的b/s 先从服务器下载源到浏览器(客户端)


<span style="font-size:18px;">package com.net.udp;

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

/**
* 服务端
* 1 创建服务端 + 端口
* 2 准备接收容器
* 3 封装成包
* 4 接收数据
* 5 分析数据
* @author lyy
*
*/
public class MyServer {
public static void main(String[] args) throws IOException {
//1 创建服务端 + 端口
DatagramSocket server = new DatagramSocket(8888);
//2 准备接收容器
byte[] container = new byte[1024];
//3 封装成包 DatagramPacket(byte[] buf, int length)
DatagramPacket packet = new DatagramPacket(container, container.length);
//4 接收数据
server.receive(packet);
//5 分析数据
byte[] data = packet.getData();
int len = packet.getLength();
System.out.println(new String(data,0,len));
//释放资源
server.close();

}
}</span>


<span style="font-size:18px;">package com.net.udp;

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

/**
* 客户端
* 1 创建客户端 + 端口
* 2 准备数据
* 3 打包(发送的地点 以及端口)
* 4 发送
* 5 释放
*
* @author lyy
*
*/
public class MyClient {

public static void main(String[] args) throws IOException {
//1 创建客户端 + 端口
DatagramSocket client = new DatagramSocket(6666);
//2 准备数据
String msg = "真的爱你";
byte[] data = msg.getBytes();
//3 打包(发送的地点 以及端口) DatagramPacket(byte[] buf, int length, InetAddress address, int port)
DatagramPacket packet = new DatagramPacket(data, data.length,new InetSocketAddress("localhost",8888));
// 4 发送
client.send(packet);
//5 释放
client.close();


}

}
</span>



6、Scoket通信

基于TCP:面向连接安全 可靠 效率低 类似于打电话

一、面向连接:请求 响应 Request——Response

二、Socket 编程

         1、服务器ServerSocket      

         2、客户端 Socket

java 网络编程(Socket) TCP/UDP 总结案例



package com.net.tcp.socket;

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

/**
* 必须先启动服务器 后连接
* 1 创建服务器 指定端口
* 2 接收客户端连接
* 3 发送数据和接收数据
*
* 接收多个客户端
* @author lyy
*
*/
public class MultServer {

public static void main(String[] args) throws IOException {
//1 创建服务区 指定端口 ServerSocket(int port)
ServerSocket server = new ServerSocket(8888);
// 2 接收客户端连接 阻塞式
while(true){//死循环 一个accept() 一个客户端
Socket socket = server.accept();
System.out.println("一个客户端建立连接");
// 3 发送数据
String msg = "欢迎使用";

DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(msg);
dos.flush();
while(true){

}
}
}

}


package com.net.tcp.socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**
* 1 创建客户端 必须指定服务器 + 端口 此时连接
* Socket(InetAddress host, int port)
* 接收数据 发送数据
* @author lyy
*
*/
public class Client {

public static void main(String[] args) throws UnknownHostException, IOException {
// 1 、创建客户端 必须指定服务器 + 端口 此时连接
Socket client = new Socket("192.168.1.112", 8888);
// 2 接收数据
//BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
//String echo = br.readLine();//阻塞式的方法
//System.out.println(echo);
DataInputStream dis = new DataInputStream(client.getInputStream());
String echo = dis.readUTF();
System.out.println(echo);


}
}


7、小案例(强烈建议大家自己敲一遍,很好玩!)

使用的多线程、流以及socket通信原理的方式,创建了一个公众聊天室的demo,进入有系统提示,可以@名字说悄悄话等等,对socket整个知识点稍微了解了更加深入一点点,还是要多消化消化,今天做了一天了,头有点大了,不说了上案例

package com.net.tcp.chat.demo4;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
* 创建服务器
* @author lyy
*
*/
public class Server {
private List<MyChanel> all = new ArrayList<MyChanel>();

public static void main(String[] args) throws IOException {
new Server().start();
}

public void start() throws IOException{
ServerSocket server = new ServerSocket(9999);
while(true){
Socket client = server.accept();
MyChanel channel = new MyChanel(client);
all.add(channel);//加入到容器中同意管理
new Thread(channel).start();//一条道路
}
}

/**
* 一个客户端一个道路
* 1 输入流
* 2 输出流
* 3 接收数据
* 4 发送数据
* @author lyy
*
*/
private class MyChanel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning = true;
private String name;

public MyChanel(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());

this.name = dis.readUTF();
this.send("欢迎你进入聊天室!");
sendOthers(this.name+"进入了聊天室",true);
} catch (IOException e) {
CloseUtil.closeAll(dis,dos);
isRunning = false;
}

}

/**
* 读取数据
* @return
*/
private String receive(){
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
CloseUtil.closeAll(dis);
isRunning = false;
all.remove(this);//移除自身
}
return msg;
}

/**
* 发送数据
*/
public void send(String msg){
if(null == msg && !msg.equals("")){
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
//e.printStackTrace();
CloseUtil.closeAll(dos);
isRunning = false;
all.remove(this);//移除自身
}
}

/**
* 发送给其他客户端
*/
private void sendOthers(String msg,boolean sys){
System.out.println(msg);
//是否为私聊 约定
if(msg.startsWith("@") && msg.indexOf(":") > -1){//表示私聊
String name = msg.substring(1, msg.indexOf(":"));
String conetnt = msg.substring(msg.indexOf(":")+1);
//获取Name
for (MyChanel other : all) {
if(other.name.equals(name)){
other.send(this.name+"对您悄悄说"+conetnt);
}
}
}else{

//遍历容器
for (MyChanel other : all) {
if(other == this){
continue;
}
if(sys){//系统信息
//发送给其他客户端
other.send("系统信息:"+msg);
}else{
//发送给其他客户端
other.send(this.name+":"+msg);
}

}
}
}

@Override
public void run() {
while(isRunning){
sendOthers(receive(),false);
}
}

}

}

package com.net.tcp.chat.demo4;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
* 发送数据线程
* @author lyy
*
*/
public class Send implements Runnable{

//控制台的输入流
private BufferedReader console;
//管道输出流
private DataOutputStream dos;
//控制线程
private boolean isRunning = true;
//名称
private String name;
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}

public Send(Socket client , String name){
this();
try {
dos = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
//e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos,console);

}
}

//从控制台接收数据
private String getMsgFromConsole(){
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();

}
return "";
}
/**
* 从控制台接收数据
* 发送数据
*/
public void send(String msg){
if(msg != null && !msg.equals("")){
try {
dos.writeUTF(msg);
dos.flush();//强制刷新
} catch (IOException e) {
//e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos,console);
}
}
}

@Override
public void run() {
//线程体
while(isRunning){
send(getMsgFromConsole());
}
}

}


package com.net.tcp.chat.demo4;

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

/**
* 接收线程
* @author lyy
*
*/
public class Receive implements Runnable{

//输入流
private DataInputStream dis;
//线程标识
private boolean isRunning = true;

public Receive() {
}
public Receive(Socket client){
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
//e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dis);
}
}

/**
* 接收数据
* @return
*/
public String receive(){
String msg ="";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
}
return msg;
}

@Override
public void run() {
//线程体
while(isRunning){
System.out.println(receive());
}
}

}


<span style="font-size:18px;">package com.net.tcp.chat.demo4;

import java.io.Closeable;
import java.io.IOException;

/**
* 关闭流的方法
* @author lyy
*
*/
public class CloseUtil {
public static void closeAll(Closeable... io){
for(Closeable temp :io){
if(null != temp){
try {
temp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
</span>
}


<span style="font-size:18px;">package com.net.tcp.chat.demo4;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**
* 创建客户端 发送数据 + 接收数据
* 写出数据 输出流
* 读取数据 输入流
* @author lyy
*
* 输入流和输出流在同一个线程内 彼此独立
*
*
*
*/
public class Client {

public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("请输入名称:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if(name.equals("")){
return;
}
Socket client = new Socket("localhost", 9999);
new Thread(new Send(client,name)).start();//一条路径
new Thread(new Receive(client)).start();//一条路径
}

}
</span>



java 网络编程(Socket) TCP/UDP 总结案例


java 网络编程(Socket) TCP/UDP 总结案例


学习了一天,感觉还是有很大的收获的,需要多消化消化,希望大家也能从中收获一点自己想要的东西,加油!




总结案例下载:http://download.csdn.net/detail/qq_14996421/9527603