黑马程序员——Java网络编程(TCP和UDP)
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a
href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! -------------------------------
概念:什么是TCP和UDP
TCP是一种面向连接的、可靠的、基于字节流的运输层通信协议。也就是说只有建立了可靠的连
接才能进行通信,因为他们是结果三次“握手”的过程,是指先发送一次数据包,问候一下,"在吗"然后等待对方确认收
到并回复一次包,最后在开始发送数据包。
比如:打电话需要先建立连接,三大运营商需建立通讯基站,通讯网络信号覆盖,通讯连接后才能通电话。A打电话B,拨通B号码,等待B接电话,B没接到(关机)就无法通讯,如果接到就
能通讯,QQ视频聊天、等都是TCP。
TCP特点:传输安全性高,适应于用于一次传输大量报文的情形,如涉及到机密重要的文件传输,远程登录等。
UDP :是指用户数据报协议,面向非连接的传输。只管发生数据出去,不管对方是否收到。
举例:发短信问候,不管对方啥时候查看,我只管发短信出去,广场喇叭广播、火车的语言播报。
UDP特点:安全度不高,传输效率快,不用建立连接,服务效率高,适用于不考虑安全度少量的数据传输。
一、UDP的发送端
package com.itheima.net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UdpSendDemo {
/**
* @param args
*
* 创建UDP发送端
* 分析:1.建立Udp的 socket服务。
* 2.将要发送的数据封装到包中、(打包数据)
* 3.通过udp的socket 服务发送
* @throws IOException
*
*
*/
public static void main(String[] args) throws IOException {
System.out.print("007呼叫发送端启动。。。。。。。。。。。");
// 1.socket 服务使用 DatagramSocket对象
DatagramSocket ds=new DatagramSocket(10086);
String str="呼叫总部,哥们来吧!";
byte[] bt=str.getBytes();
//数据封装到对象包中
DatagramPacket dp=new DatagramPacket(bt, bt.length,InetAddress.getByName("192.168.1.110"),10000);
// ds对象的send方法发送出去
ds.send(dp);
ds.close();
}
}
二.UDP接收端:
package com.itheima.net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UdpReceDemo {
/**
* @param args
* 创建UDP接收
* 分析:1.建立Udp的 socket服务。明确一个端口
* 2.将创建数据包 接收存储收到的数据信息,方便解析
* 3.socket 的接收Reseive 方法接收存储数据
* 4.通过数据包解析数据
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// 1.socket 服务使用 DatagramSocket对象
DatagramSocket ds=new DatagramSocket(10086);
// 2.创建包数据封装到对象包中
String str="总部 服务接收启动!";
byte[] bt=str.getBytes();
DatagramPacket dp=new DatagramPacket(bt, bt.length);
//3.接收数据
ds.receive(dp);
//4.通过数据包解析数据
String ip=dp.getAddress().getHostAddress();//获取host地址
int port=dp.getPort(); //获取端口
String text=new String(dp.getData(),0,dp.getLength());
System.out.print(ip+":"+port+":"+text);
ds.close();
}
}
聊天程序(多线程)
package com.itheima.net;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class ChatDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1.发送端服务对象
DatagramSocket send=new DatagramSocket();
//Send s=new Send();
//2.接收多服务对象
DatagramSocket Res=new DatagramSocket(10001);
//Rese r=new Rese();
Thread t1=new Thread(new Send(send));
t1.start();
Thread t2 =new Thread(new Rese(Res));
t2.start();
}
}
class Send implements Runnable{
private DatagramSocket ds;
public Send(DatagramSocket send) {
// TODO Auto-generated constructor stub
}
public void Send(DatagramSocket ds){
this.ds=ds;
}
@Override
public void run() {
try {
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bufr.readLine())!=null){
byte[] bt=line.getBytes();
//数据封装到对象包中
DatagramPacket dp=new DatagramPacket(bt, bt.length,InetAddress.getByName("192.168.1.255"),10001);
if("888".equals(line)){
break;
}
ds.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
class Rese implements Runnable{
//1.创建服务对象
private DatagramSocket ds;
public Rese(DatagramSocket res) {
// TODO Auto-generated constructor stub
}
public void Rese(DatagramSocket ds){
this.ds=ds;
}
@Override
public void run() {
try {
while(true){
//2. 接收数据包
byte [] bt=new byte[1024*4];
DatagramPacket dp=new DatagramPacket(bt, bt.length);
//3.接收数据
ds.receive(dp);
//4.通过数据包解析数据
String ip=dp.getAddress().getHostAddress();//获取host地址
int port=dp.getPort(); //获取端口
String text=new String(dp.getData(),0,dp.getLength());
System.out.print(ip+":"+port+":"+text);
if("888".equals(text)){
System.out.print("退出聊天室,天晚了回家睡觉、、、、");
}
ds.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
三.TCP 建立客户端
package com.itheima.net;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClientDemo {
/**
* @param args
* 客户端发送到服务器端,TCP传输过程
* 分析思路:1.创建TCP客户端socket 服务对象,使用该对象创建一个明确的目的地,链接主机。
* 2.如果链接成功,说明传输通道已经建立,通道就是socket流,是底层建立好的,有输入输出,
* 可以通过socket获取输入输出对象 ,getOutputStream(),,getInputStream()来获取字节流
* 3.使用输入输出流,读写数据
* 4.关闭资源
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建客户端服务对象
Socket st=new Socket("192.168.1.100",10002);
//2.获取输出流
OutputStream out=st.getOutputStream();
//3.输出的数据写出去
String str="TCP上传,哥们我又来了欢迎不?";
out.write(str.getBytes());
//4.关闭
st.close();
}
}
报错:
Exception in thread "main" java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at com.itheima.net.TcpClientDemo.main(TcpClientDemo.java:24)
四:TCP建立服务端
package com.itheima.net;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServerDemo {
/**
* @throws IOException
* @Author hutian
* 服务端接收客户端发送的数据,打印出来
* TCP服务器端思路:
* 分析:1.同样要创建socket 服务,建立ServerSocket服务端对象
* 2.服务端必须对外提供端口,否则无法连接
* 3.获取连接过来的客户端对象
* 4.通过客户端对象读取,客户端发送过来的数据,并打印出来
* 5.关闭流
*/
public static void main(String[] args) throws IOException {
// 创建服务端对象
ServerSocket ss=new ServerSocket(10002); //记得要提供端口
//获取客户端
Socket sk=ss.accept(); //阻塞式
String ip=ss.getInetAddress().getHostAddress();
//通过Socket 对象getInputStream()获取输入流
InputStream in=sk.getInputStream();
byte[] bt=new byte[1024];
int len=0;
while((len=in.read(bt))!=-1){
String text=new String(bt,0,len);
System.out.print(ip+":"+text);
}
ss.close();
sk.close();
}
}
TCP 建立交互方式
1.客户端
package com.itheima.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo2 {
/**
* @param args
* 客户端发送到服务器端,TCP传输过程
* 分析思路:1.创建TCP客户端socket 服务对象,使用该对象创建一个明确的目的地,链接主机。
* 2.如果链接成功,说明传输通道已经建立,通道就是socket流,是底层建立好的,有输入输出,
* 可以通过socket获取输入输出对象 ,getOutputStream(),,getInputStream()来获取字节流
* 3.使用输入输出流,读写数据
* 4.关闭资源
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建客户端服务对象
Socket st=new Socket("192.168.1.100",10002);
//2.获取输出流
OutputStream out=st.getOutputStream();
//3.输出的数据写出去
String str="TCP上传,哥们我又来了欢迎不?";
out.write(str.getBytes());
//读取服务端返回的数据
InputStream in=st.getInputStream();
byte[] bt=new byte[1024*4];
int len=in.read(bt);
String text=new String(bt,0,len);
System.out.print(text);
//4.关闭
st.close();
}
}
2.服务端
package com.itheima.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo2 {
/**
* @throws IOException
* @Author hutian
* 服务端接收客户端发送的数据,打印出来
* TCP服务器端思路:
* 分析:1.同样要创建socket 服务,建立ServerSocket服务端对象
* 2.服务端必须对外提供端口,否则无法连接
* 3.获取连接过来的客户端对象
* 4.通过客户端对象读取,客户端发送过来的数据,并打印出来
* 5.关闭流
*/
public static void main(String[] args) throws IOException {
// 创建服务端对象
ServerSocket ss=new ServerSocket(10004); //记得要提供端口
//获取客户端
Socket sk=ss.accept(); //阻塞式
String ip=ss.getInetAddress().getHostAddress();
//通过Socket 对象getInputStream()获取输入流
InputStream in=sk.getInputStream();
byte[] bt=new byte[1024];
int len=in.read(bt);
String text=new String(bt,0,len);
System.out.print(ip+":"+text);
// 使用客户端对象输出流 给客户端发送数据
OutputStream out=sk.getOutputStream();
out.write("总部收到over".getBytes());
ss.close();
sk.close();
}
}
小结一下:1.无论客户端还是服务端,显得创建Socket 服务对象 客户端要指定端口访问
2.客户端发送,输出流,把数据写出去告诉人家
3.服务端对象先获取客户端对象,用他获取输进来的流数据,使用客户端输出流返回客户端一个信息
操作的是客户端。
问题:老是提示ip地址占用
Exception in thread "main" java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:96)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:175)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at com.itheima.net.ServerDemo2.main(ServerDemo2.java:24)
练习:上传服务端与客户端
1.客户端:
package com.itheima.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
System.out.print("来吧,等你上传服务端。。。。。");
ServerSocket ss=new ServerSocket(10008);
//2.获取到客户端对象
Socket sk=ss.accept();
System.out.print(sk.getInetAddress().getHostAddress()+"......成功连接");
BufferedReader bufr=new BufferedReader(new InputStreamReader(sk.getInputStream()));
BufferedWriter bufw=new BufferedWriter(new FileWriter("D:\\log.txt"));
String line=null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
// bufw.close();
bufw.flush();
}
//
PrintWriter out=new PrintWriter(sk.getOutputStream(),true);
out.print("恭喜您,上传成功啦!");
bufw.close();
ss.close();
sk.close();
}
}
打印:
请注意,我要上传文件啦。。。。。
true
Exception in thread "main" java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
2.服务端
package com.itheima.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
System.out.println("亲来吧,等你上传服务端。。。。。");
ServerSocket ss=new ServerSocket(10008);
//2.获取到客户端对象
Socket sk=ss.accept();
System.out.print(sk.getInetAddress().getHostAddress()+"......成功连接");
BufferedReader bufr=new BufferedReader(new InputStreamReader(sk.getInputStream()));
BufferedWriter bufw=new BufferedWriter(new FileWriter("D:\\server.txt"));
String line=null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
// bufw.close();
bufw.flush();
}
//
PrintWriter out=new PrintWriter(sk.getOutputStream(),true);
out.print("恭喜您,上传成功啦!");
bufw.close();
ss.close();
sk.close();
}
}
打印:
来吧,等你上传服务端。。。。。
Exception in thread "main" java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:96)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:175)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at com.itheima.net.UploadServer.main(UploadServer.java:22)
TCP和UDP总结:
TCP: 1.建立连接,形成传输数据的通道。
2.在连接中进行大数据传输。
3.通过三次握手完成连接,是可靠协议。
4.因为必须建立连接,所以效率会稍低。
主要用于数据下载,文件传输,可靠性要求高的应用
UDP: 1.将数据及源和目的封装成数据包中,不需要建立连接。
2.每个数据报包的大小在限制在64k内。
3.因无连接,是不可靠的协议。
4.不需要建立连接,速度快。
应用:传输视频,mp3等
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a
href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! -------------------------------