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();
}
}
}