**
**
1.TCP协议通信
package com.itheima.demo01.TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
TCP通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据
表示客户端的类:
java.net.Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
套接字:包含了IP地址和端口号的网络单位
构造方法:
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
参数:
String host:服务器主机的名称/服务器的IP地址
int port:服务器的端口号
成员方法:
OutputStream getOutputStream() 返回此套接字的输出流。
InputStream getInputStream() 返回此套接字的输入流。
void close() 关闭此套接字。
实现步骤:
1.创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号
2.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
3.使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据
4.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
5.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据
6.释放资源(Socket)
注意:
1.客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
2.当我们创建客户端对象Socket的时候,就会去请求服务器和服务器经过3次握手建立连接通路
这时如果服务器没有启动,那么就会抛出异常ConnectException: Connection refused: connect
如果服务器已经启动,那么就可以进行交互了
*/
public class TCPClient {
public static void main(String[] args) throws IOException {
//1.创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号
Socket socket = new Socket("127.0.0.1",8888);
//2.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
OutputStream os = socket.getOutputStream();
//3.使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据
os.write("你好服务器".getBytes());
//4.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//5.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//6.释放资源(Socket)
socket.close();
}
}
package com.itheima.demo01.TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*
TCP通信的服务器端:接收客户端的请求,读取客户端发送的数据,给客户端回写数据
表示服务器的类:
java.net.ServerSocket:此类实现服务器套接字。
构造方法:
ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
服务器端必须明确一件事情,必须的知道是哪个客户端请求的服务器
所以可以使用accept方法获取到请求的客户端对象Socket
成员方法:
Socket accept() 侦听并接受到此套接字的连接。
服务器的实现步骤:
1.创建服务器ServerSocket对象和系统要指定的端口号
2.使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket
3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
4.使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据
5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
6.使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据
7.释放资源(Socket,ServerSocket)
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
//1.创建服务器ServerSocket对象和系统要指定的端口号
ServerSocket server = new ServerSocket(8888);
//2.使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket
Socket socket = server.accept();
//3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//4.使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
OutputStream os = socket.getOutputStream();
//6.使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据
os.write("收到谢谢".getBytes());
//7.释放资源(Socket,ServerSocket)
socket.close();
server.close();
}
}
2.UDP协议通信:详细思路已展示在代码注释中。(以下题目是网络上出现次数比较多的题目,小白写法可能过于简略,但是普遍做法均千篇一律,博友有问题可以一起探讨,或另辟蹊径。)
1-1 假设Tom和Jerry利用Java UDP进行聊天,请为他们编写程序。具体如下:
(1)、Tom和Jerry聊天的双方都应该具有发送端和接收端;
(2)、利用DatagramSocket与DatagramPacket;
(3)、实现 java.lang.Runnable类,重写 run()方法。
Jerry
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
//Jerry客户端
Thread t1 = new Thread(new Runnable() {
//创建数据报套接字并将其绑定到本地主机上的指定端口
DatagramSocket data = new DatagramSocket(2021);
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b, b.length);
@Override
public void run() {
// TODO 自动生成的方法存根
while(true) {
try {
data.receive(dp);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("TOM:"+new String(dp.getData(),0,dp.getLength()));
}
}
});
//服务器
Thread t2 = new Thread(new Runnable() {
byte[] b = new byte[1024];
String str;
Scanner in = new Scanner(System.in);
DatagramPacket dp = new DatagramPacket(b, b.length,InetAddress.getByName("127.0.0.1"),8888);
DatagramSocket ds = new DatagramSocket(8083,InetAddress.getByName("127.0.0.1"));
@Override
public void run() {
while(true) {
str = in.next();
dp.setData(str.getBytes());
try {
assert ds!=null;
ds.send(dp);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
});
t1.start();
t2.start();
}
}
Tom
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
//发送线程
Thread t1 = new Thread(new Runnable() {
DatagramSocket data = new DatagramSocket(8888);
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b, b.length);
@Override
public void run() {
// TODO 自动生成的方法存根
while(true) {
try {
data.receive(dp);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("Jerry:"+new String(dp.getData(),0,dp.getLength()));
}
}
});
//接收线程
Thread t2 = new Thread(new Runnable() {
byte[] b = new byte[1024];
String str;
Scanner in = new Scanner(System.in);
//构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
DatagramPacket dp = new DatagramPacket(b, b.length,InetAddress.getByName("127.0.0.1"),2021);
//创建数据报套接字,将其绑定到指定的本地地址。
DatagramSocket ds = new DatagramSocket(8088,InetAddress.getByName("127.0.0.1"));
@Override
public void run() {
while(true) {
str = in.next();
dp.setData(str.getBytes());
try {
assert ds!=null;
ds.send(dp);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
});
t1.start();
t2.start();
}
}
注:可使用ideas或者explise实现打开多个端口查看通信。
1-2 利用Java Socket编写一个简单的Web服务器,具体如下:
(1)、使用 ServerSocket 监听某一端口,然后等待连接获取 Socket对象;
(2)、创建一个类 HttpServer 继承 java.lang.Thread 类,重写 run()方法,执行浏览器请求;
(3)、获得浏览器请求,解析资源文件路径;
(4)、读取资源文件,响应给浏览器;
(5)、浏览器地址栏输入: http://localhost:8000/index.html;
(6)、代码如下:
package 计算机网络实验;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer extends Thread{
ServerSocket serverSocket = null;
public HttpServer(ServerSocket socket){
this.serverSocket = socket;
}
@Override
public void run(){
while(true){
byte[] b = new byte[1024];
int len = -1;
OutputStream outputStream = null;
PrintWriter pw = null;
try {
// 监听来自前台的消息请求
Socket accept = serverSocket.accept();
InputStreamReader read = new InputStreamReader(accept.getInputStream());
BufferedReader bufferedReader = new BufferedReader(read);
//获取头
String str = bufferedReader.readLine();
String[] split = str.split("/");
String temp = split[1];
String[] source = temp.split(" +");
// 判断资源
if(source[0].equals("index.html")){
outputStream = accept.getOutputStream();
// 获取index.html的输入流
InputStream is = new FileInputStream("此处雯html文件地址 index.html");
int lens = is.available();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
System.out.println("reader" + reader);
StringBuffer sb = new StringBuffer();
String data = null;
while ((data = reader.readLine()) != null) {
sb.append(data).append("\r\n");
}
StringBuffer result = new StringBuffer();
result.append("HTTP /1.1 200 ok \r\n"); // 设置HTTP响应格式
result.append("Content-Type:text/html \r\n");
result.append("Content-Length:" + lens+ "\r\n");
result.append("\r\n" + sb.toString());
System.out.println(result.toString());
outputStream.write(result.toString().getBytes()); // 写到输入流中
outputStream.flush();
outputStream.close();
}
accept.close(); // 关闭套接字
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package 计算机网络实验;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer extends Thread{
ServerSocket serverSocket = null;
public HttpServer(ServerSocket socket){
this.serverSocket = socket;
}
@Override
public void run(){
while(true){
byte[] b = new byte[1024]; // 缓冲数组
int len = -1;
OutputStream outputStream = null;
PrintWriter pw = null;
try {
// 监听来自前台的消息请求
Socket accept = serverSocket.accept();
InputStreamReader read = new InputStreamReader(accept.getInputStream());
BufferedReader bufferedReader = new BufferedReader(read);
//获取头
String str = bufferedReader.readLine();
String[] split = str.split("/");
String temp = split[1];
String[] source = temp.split(" +");
// 判断资源
if(source[0].equals("index.html")){
outputStream = accept.getOutputStream();
// 获取index.html的输入流
InputStream is = new FileInputStream("此处为html文件地址index.html");
int lens = is.available();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
System.out.println("reader" + reader);
StringBuffer sb = new StringBuffer();
String data = null;
while ((data = reader.readLine()) != null) {
sb.append(data).append("\r\n");
}
StringBuffer result = new StringBuffer();
以下四行为http协议固定格式,暂时可不做处理。
result.append("HTTP /1.1 200 ok \r\n");
result.append("Content-Type:text/html \r\n");
result.append("Content-Length:" + lens+ "\r\n");
result.append("\r\n" + sb.toString());
System.out.println(result.toString());
outputStream.write(result.toString().getBytes()); // 写到输入流中
outputStream.flush();
outputStream.close();
}
accept.close(); // 关闭套接字
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Html文本格式
```c
```c
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Server for YJL</title>
</head>
<body>
<h1>Hello World! Welcome to my webserver!</h1>
<font color="red"><h2>hello world</h2></font>
</body>
</html>