java 网络编程(Socket) TCP/UDP 总结案例
Posted 牧小农
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 网络编程(Socket) TCP/UDP 总结案例相关的知识,希望对你有一定的参考价值。
网络编程:关注的是底层的数据传输
网页编程:数据的展示
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、 后拆分
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(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>
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();
}
}
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>
基于TCP:面向连接安全 可靠 效率低 类似于打电话
一、面向连接:请求 响应 Request——Response
二、Socket 编程
1、服务器ServerSocket
2、客户端 Socket
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>
学习了一天,感觉还是有很大的收获的,需要多消化消化,希望大家也能从中收获一点自己想要的东西,加油!
总结案例下载:http://download.csdn.net/detail/qq_14996421/9527603
以上是关于java 网络编程(Socket) TCP/UDP 总结案例的主要内容,如果未能解决你的问题,请参考以下文章
细说http - tcp - udp - socket - protobuf协议