Socket就是一个Java类,底层协议TCP/UDP
这个类的目的就是底层通过协议进行两端的关联
需要深入了解的是TCP协议(特点:三次握手、四次挥手)
其底层是基于字节型流执行操作
1、利用Socket进行连接
TCP协议
服务端 ServerSocket
客户端 Socket
2、如何利用流进行通信
获取字节流进行传输
输出 OutputStream os =socket.getInputStream();
输入 InputStream is = socket.getOutputStream();
为了传递字符方便 可以做一些包装
PrintWriter pw = new PrintWriter(os); 字符输出打印流
pw.priintln(“ “);//可以发送一行信息过去
InputStreamReader isr = new InputStreamReader(is); 字节字符转换流
//可以将字节型的流转换成字符型
BufferedReader br = new BufferedReader(isr); 高级字符输入流
//可以一次读取一行
3、可能出现的问题
3.1)SocketException:Connection reset ——> 这是一个说明性异常,我在等待接收对方信息时,对方下线了
异常的原因:
一端退出,但退出时并未关闭该连接
另一端如果在从连接中读数据则抛出该异常(Connection reset)
简单的说就是在连接断开后的读和写操作引起的。
3.2)发送和接收都需要顺序
发送端和接受端同一时刻只能有一端在传送数据
为了解决收发顺序问题 —-> 可以利用线程
实现多线程方式
服务端两个线程,一个接收,一个发送
客户端两个线程,一个接收,一个发送
3.3)有了线程之后,两端可以进行自由的通信
但是真正的聊天软件,服务端是不会说话的,应该是客户端和客户端进行交流
能不能有多个客户端连接同一个服务器?
如果能,怎么连接?
如果连接了,客户端有很多个,服务端只有一个,服务端需要存储好多个客户端的socket,怎么存?—-> 集合
Map
所以当客户端之间相互通信时,服务端相当于一个中转,负责读取客户端的消息,转发给另一个客户端
服务端:
/*** 这是服务端*/public class Server {public static void main(String[] args){//new对象时底下有红线通常有三种情况//1.抽象类 或者 接口 不让new//2.需要传参数//3.编译时异常 可能需要捕获异常try {System.out.println("---------server start---------");//1.创建服务器对象ServerSocket 需要给参数 即开放的端口号//端口号 0 - 65535 一般不选3000以下的 被占用了ServerSocket server = new ServerSocket(8888);//2.等待客户端连接Socket socket = server.accept();//同意连接 如果没有人来 就一直等//若能成功获取到这个socket类 证明连接成功//连接成功后 服务端可以对客户端说一句话//通过客户端获取一个字节型输出流OutputStream os = socket.getOutputStream();//用字节流写文字不方便 可将字节流包装成字符流 为了发送一行文字PrintWriter writer = new PrintWriter(os);//发送文字writer.println("连我干嘛?");writer.flush();//服务端接收客户端信息//获取输入流InputStream is = socket.getInputStream();//包装成字符型InputStreamReader isr = new InputStreamReader(is);//再包装 让其可以读一行BufferedReader br = new BufferedReader(isr);String value = br.readLine();System.out.println(value);} catch (IOException e) {e.printStackTrace();}}}
客户端:
/*** 这是客户端*/public class Client {public static void main(String[] args){try {System.out.println("----client start----");//1.主动发起对服务器的访问//需要两个参数 第一个是服务器的地址 第二个是端口号Socket socket = new Socket("localhost",8888);//若能成功创建socket对象 则与服务器连接成功//连接成功后服务器发了一句话过来 客户端须接受//获取一个输入流InputStream is = socket.getInputStream();//将字节型流转换成字符型InputStreamReader inr = new InputStreamReader(is);//将字符流再包装一次 目的是为了一次可以读取一行 跟服务端统一BufferedReader reader = new BufferedReader(inr);//读取一行数据String value = reader.readLine();System.out.println(value);//客户端给服务端说话//获取一个输出流OutputStream os = socket.getOutputStream();//包装成字符型PrintWriter pw = new PrintWriter(os);pw.println("哈哈哈 连你咋地?");pw.flush();} catch (IOException e) {e.printStackTrace();}}}
