客户端
Socket类
Socket类底层的协议是TCP协议(传输控制协议,在传输层),可以给你想要获取数据的地址(ip地址)发送请求,然后获取数据。
方法:
构造函数
public Socket(String host,int port);//"ip地址",端口号,如:127.0.0.1,5000
发数据
public OutputStream getOutputStream();//返回的是OutputStream对象
收数据
public InputStream getInputStream();//返回InputStream对象
Socket执行IO流时会出现阻塞,也就是会阻塞其他的IO流的读写,因此要把与IO流相关的操作放在线程内执行(也就是放在run方法内,最好使用线程池的方式,这样做比较省资源)。
URL类
URL类也是用来给想要获取数的地址发送请求,以此来获得数据的,不过它获取的格式不同,需要写上协议,还有就是它不会像Socket类那样返回响应的开头信息。
构造方法
public URL(String spec);//填的是ip地址,格式如:http://ip地址:端口/资源地址,端口号可以省略建立连接
public URLConnection openConnection();//它会抛出IOException异常,返回URLConnection对象
返回的URLConnection对象拿到服务器返回的结果,抛出IOException
public InputStream getInputStream();//读入返回的结果
把返回的结果写入,抛出IOException
public OutputStream getOutputStream();
服务器端
ServerSocket类
它是用来等待客户端发送请求的类,也就是等待请求网络传入。
方法:
构造函数
//port是端口号,你可以随意定义(在范围内0~65535,尽量使用4位以上的端口),抛出IOException异常,客户端通过该端口对服务器发送请求
public ServerSocket(int port);
等待
public Socket accept();//等待客户端连上服务器,抛出IOException异常
代码演示
1、客户端和服务器端的交互
服务器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Server {
public static void main(String[] args) {
try {
//设置服务器端口,建议使用4位的
ServerSocket serversocket = new ServerSocket(5500);
//创建线程池,但方便处理多线程,你也可以使用其他的线程池
ThreadPoolExecutor service = new ThreadPoolExecutor(10, 11, 5000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
System.out.println("等待连接...");
while(true){
//等待客户端连接
Socket socket=serversocket.accept();
System.out.println("已连接...");
//把相关io流放在线程内处理,可以避免线程多,从而引起的阻塞,submit就是提交任务,把任务交给线程池
service.submit(()-> {
io(socket);
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void io(Socket socket) {
try {
//获得客户端的数据
InputStream in = socket.getInputStream();
//服务器写入客户端数据
OutputStream out = socket.getOutputStream();
int len=0;
byte[] bytes = new byte[1024 * 8];
//把获得的数据在服务器端读出来
while((len=in.read(bytes))!=-1){
String s = new String(bytes,0,len,"utf-8");
System.out.println("客户端说:"+s);
//写入客户端
out.write(("服务器端回答:"+s).getBytes("utf-8"));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
//设置客户端地址以及要访问的服务器所在端口,之前设置的那个服务器的端口是5500
Socket socket = new Socket("localhost", 5500);
//获得输出流,把客户端的说内容写入服务器
OutputStream out = socket.getOutputStream();
//因为要在客户端进行多次输入,这会造成io流的阻塞,因为线程是并行的,有可能会一起进去操作,这就造成了阻塞,因此需要线程进行处理
new Thread(()->{
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()){
String next = sc.nextLine();
try {
//把客户端说的话写入服务器
out.write(next.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//读取服务端的回答
InputStream in = socket.getInputStream();
int len=0;
byte[] bytes = new byte[1024 * 8];
//读入服务端写入的回答
while((len=in.read(bytes))!=-1){
String result = new String(bytes, 0, len, "utf-8");
System.out.println(result);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果
服务器端界面
等待连接...
已连接...
客户端说:晚上好
客户端说:早上好
客户端说:下午好
客户端界面
晚上好
服务器端回答:晚上好
早上好
服务器端回答:早上好
下午好
服务器端回答:下午好
2、从网上下载一张图片
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class DownLoad {
public static void main(String[] args) {
try {
//用URL定位你要下载的图片,并且打开链接与这个图片的地址相连接
HttpURLConnection connection=(HttpURLConnection) new URL("https://csdnimg.cn/pubfooter/images/csdn-kf.png").openConnection();
//读取要获得的图片数据
InputStream in = connection.getInputStream();
int len=0;
byte[] bytes = new byte[1024 * 8];
//写入需要存放的地方
FileOutputStream out = new FileOutputStream("E:\\photo.png");
while((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
System.out.println("下载完毕");
//关闭流和连接
out.close();
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果
下载完毕