UDP----发送端/接收端
public class demo2 {
//通过UDP协议完成一个聊天程序
//一个负责发送,一个负责接收.两个任务需要同时进行
//使用多线程技术
public static void main(String[] args) throws UnknownHostException, SocketException {
DatagramSocket send = new DatagramSocket();
DatagramSocket rece = new DatagramSocket(20000);
new Thread(new Send(send)).start();
new Thread(new Rece(rece)).start();
}
}
class Send implements Runnable {
/*
* 建立UDP发送端
* 思路:
* 1, 建立可以实现UDP传输的Socket服务
* 2, 明确具体发送的数据
* 3, 将数据封装成数据包
* 4, 通过socket服务将具体数据发送出去
* 5, 关闭服务
* */
private DatagramSocket ds;
Send(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
//具体发送数据的任务内容
//1, 要发送的数据来自哪里 键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//2, 将数据封装到数据包
String line = null;
try {
while ((line = br.readLine()) != null) {
byte[] bytes = line.getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.1.7"), 20000);
//3, 将数据包发送出去
ds.send(dp);
if (line.equals("over")) {
break;
}
}
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接收端
class Rece implements Runnable {
private DatagramSocket ds;
Rece(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
while (true) {
byte[] bytes = new byte[1024];
//创建数据包对象
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
try {
ds.receive(dp); //接收到的数据储存到数据包中
} catch (IOException e) {
e.printStackTrace();
}
//获取数据
String ip = dp.getSocketAddress().toString();
String str = new String(dp.getData(), 0, dp.getLength());//返回数据缓冲区
System.out.println(ip + " : " + str);
if (str.equals("over")) {
System.out.println(ip + " -- 离开了~~~~~~");
}
}
}
}
TCP----客户端/服务端
- Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序。
客户端 Socket
/*
* TCP客户端建立
* 思路:
* 1, 建立TCP客户端socket服务,明确目的地址和端口
* 2, 一旦连接建立, 就有了传输数据的通道,这个传输通道是通过IO流实现的,Socket IO流
* 3, 只要获取Socket IO流,使用其中的写动作就可以将数据写到socket流中发送到服务端
* 4, 关闭资源
* */
//客户端发送数据给服务端,并读取服务端反馈的数据
//1, 创建Socket客户端 明确目的地址和端口
System.out.println("客户端启动~~~~~~~~~");
Socket socket = new Socket("192.168.1.7", 10080);
//2, 获取socket流中的输出流,将数据发送到服务端
OutputStream out = socket.getOutputStream();
//3, 通过输出流写数据
out.write("注意了,TCP客户端来了~~~~~~".getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int num = is.read(bytes);
String str = new String(bytes, 0, num);
System.out.println(str);
//4, 关闭资源
socket.close();
服务器端 ServerSocket
/*
* 创建TCP服务器端
* 思路:
* 1, 创建Socket服务器端 ,服务器端为了能让客户端连接上,必须提供端口(监听一个端口)
* 2, 获取客户端对象, 通过客户端的socket流和对应客户端进行通信
* 3, 获取客户端socket流的读取流
* 4, 读取数据,显示在服务器端
* 5, 关闭资源
* */
System.out.println("服务器端启动~~~~~~~~~");
//1, 创建客户端对象
ServerSocket serverSocket = new ServerSocket(10080);
//2, 获取客户端对象
Socket socket = serverSocket.accept();//监听是否有客户端对象连接进来
String ip = socket.getInetAddress().getCanonicalHostName();//获取IP地址
//3, 通过客户端对象获取socket流的读取流
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int num = is.read(bytes);
String str = new String(bytes, 0, num);
System.out.println(ip + " : " + str);
//4, 通过客户端对象获取socket流的输出对象
OutputStream os = socket.getOutputStream();
os.write("服务端收到了~~~~~~".getBytes());
socket.close();
serverSocket.close();
TCP上传文本示例------
public static void main(String[] args) throws IOException {
//客户端发送数据给服务端,并读取服务端反馈的数据
// 创建Socket客户端 明确目的地址和端口
System.out.println("客户端启动~~~~~~~~~");
Socket socket = new Socket("192.168.1.7", 10080);
//创建本地文件输入流
BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream("E:\\a.txt")));
// 获取socket流中的输出流,将数据发送到服务端
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
// OutputStream out = socket.getOutputStream();
// BufferedWriter bfw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//频繁读写,将数据写到sock输出流中
String line = null;
while ((line = bfr.readLine()) != null) {
pw.println(line);
}
//使用socket 的禁止输出流方法,向服务端发送停止标记
socket.shutdownOutput();
//获取socket流读取流,读取服务端反馈的信息
BufferedReader bfrIN = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String string=null;
while ((string=bfrIN.readLine())!=null){
System.out.println(string);
}
// 关闭资源
socket.close();
bfr.close();
}
---------------***********************************------------------
public static void main(String[] args) throws IOException {
System.out.println("服务器端启动~~~~~~~~~");
//1, 创建服务端对象
ServerSocket serverSocket = new ServerSocket(10080);
//2, 获取客户端对象
Socket socket = serverSocket.accept();
String ip = socket.getInetAddress().getCanonicalHostName();
//获取socket流中读取流
BufferedReader bfrIN = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//数据存储目的地
PrintWriter pw = new PrintWriter(new FileWriter("E:\\aa.txt"), true);
//频繁读写,将数据写到目的地
String line = null;
while ((line = bfrIN.readLine()) != null) {
pw.println(line);
}
//向客户端发送反馈数据
PrintWriter pwOut = new PrintWriter(socket.getOutputStream(), true);
pwOut.print("上传成功 ");
pwOut.flush();
socket.close();
serverSocket.close();
pw.close();
}
图片上传示例------解决重名,并发访问
public static void main(String[] args) throws IOException {
//客户端发送数据给服务端,并读取服务端反馈的数据
// 创建Socket客户端 明确目的地址和端口
System.out.println("客户端启动~~~~~~~~~");
Socket socket = new Socket("192.168.1.7", 10080);
//创建本地文件输入流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("E:\\1.jpg"));
// 获取socket流中的输出流,将数据发送到服务端
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream()); //使用缓冲区技术
//频繁读写,将数据写到sock输出流中
byte[] bytes=new byte[1024];
int num=0;
while ((num=bis.read(bytes))!=-1){
bos.write(bytes,0,num);
bos.flush();
}
//使用socket 的禁止输出流方法,向服务端发送停止标记
socket.shutdownOutput();
//获取socket流读取流,读取服务端反馈的信息
BufferedReader bfrIN = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String string=null;
while ((string=bfrIN.readLine())!=null){
System.out.println(string);
}
// 关闭资源
socket.close();
bis.close();
}
*********************************************************************
public static void main(String[] args) throws IOException {
System.out.println("服务器端启动~~~~~~~~~");
// 创建服务端对象
ServerSocket serverSocket = new ServerSocket(10080);
while (true) {
// 获取客户端对象
Socket socket = serverSocket.accept();//监听是否有客户端对象连接进来
new Thread(new picout(socket)).start(); //解决并发访问问题
}
}
class picout implements Runnable {
private Socket socket;
picout(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
String ip = socket.getInetAddress().getCanonicalHostName();
System.out.println(ip + "--------连接到服务器");
//获取socket流中读取流
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//解决命名重复问题
int count = 1;
File dir = new File("E:\\pic");
File file = new File(dir, ip + "(" + count + ").jpg");
while (file.exists()) {
count++;
file = new File(dir, ip + "(" + count + ").jpg");
}
//数据存储目的地
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); //使用缓冲区技术
//频繁读写,将数据写到目的地
byte[] bytes = new byte[1024];
int num = 0;
while ((num = bis.read(bytes)) != -1) {
bos.write(bytes, 0, num);
bos.flush();
}
// 通过客户端对象获取socket流的输出对象,输出反馈信息
PrintWriter pwOut = new PrintWriter(socket.getOutputStream(), true);
pwOut.print("上传成功 ");
pwOut.flush();
socket.close(); //关闭资源
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
自定义服务器,浏览器给服务器发送的请求信息如下
Http协议请求头
GET / HTTP/1.1 //请求行
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
Host: 192.168.1.7:10080
Connection: Keep-Alive
*/
***********************************
服务端的应答信息
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"48-1551884610418"
Last-Modified: Wed, 06 Mar 2019 15:03:30 GMT
Content-Type: text/html
Content-Length: 48
Date: Wed, 20 Mar 2019 04:11:37 GMT
Connection: close
URL对象
String str_url = "http://192.168.1.7:8080/myweb/HTML1.html?name=lisi";
URL url = new URL(str_url);
System.out.println("Protocol : " + url.getProtocol());
System.out.println("Host : " + url.getHost());
System.out.println("Prot : " + url.getPort());
System.out.println("Path : " + url.getPath());
System.out.println("File : " + url.getFile());
System.out.println("Query : " + url.getQuery());
//通过url.openConnection(); 获取该远程资源的链接对象(内部封装了socket客户端)
URLConnection uc=url.openConnection();
System.out.println(uc);
InputStream is=uc.getInputStream();
byte[] bytes =new byte[1024];
int num=is.read(bytes);
String s=new String(bytes,0,num);
System.out.println(s);
System.out.println("得到反馈信息了");
网络架构
C/S Client Server
- 特点:
客户端和服务端都要编写
客户端需要维护
客户端可以分担部分运算
如:大型运算,比如网络游戏
B/S Browser Server
- 特点
只需编写服务端,客户端就是已有的浏览器
客户端不需要维护
运算全在服务端
如:网页游戏