一般,就这么的形式,熟悉后就这么用了。
客户端:
首先,创建客户端套接字
Socket s = new Socket(ip, port);
通过套接字,可以获得输入流和输出流
InputStream is = s.getInputStream();
OutputStream os = s.getOutStream();
接下来就是对输入流和输出流的装饰了,例如:
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(os));
一个聊天系统,客户端应该是这样的:
1.可以给其他人发送信息
2.可以接收其他人的信息
3.发送和接收互不干扰
所以,需要用两条线程,控制发送和接收
发送又发送事件进行处理
下面是接收信息线程里面的内容:
public void run() {
DataInputStream dis = new DataInputStream(new BufferedInputStream(s.getInputStream));
while(true) {
String msg = dis.readUTF();
// 退出循环
if(msg.equal("bye")) {
break;
}
}
}
注:
Bufferreader与Bufferedinputstream区别是什么?
前者是读取字符流,后者是读取字节流,没有好坏之别
BufferInputStream,这个是 java.io 包里面的对象,叫做缓冲输入流.
创建 BufferedInputStream 时即创建了一个内部缓冲区数组。
读取是直接从缓冲区里面去取,不是直接到文件.所以读取的速度大大的提高.
在构造时可以根据需求,指定缓冲区的大小
BufferedInputStream先读取比请求更多的数据到缓冲区,当调用read时如果数据已经在缓存区,
则直接返回对应数据不做IO操作,否则去读取新的数据到缓冲区(通常比请求的数据要多),
服务器端:
一个聊天系统,服务器端是这样的:
1.可以接收客户端发送的消息
2.将客户端的消息转发
3.随时接收和转发每一个客户端的消息
创建服务器端套接字
ServerSocket ss = new ServerSocket(8080);
使用一个循环接收多个客户端的连接,常用的办法是使用一个循环:
while(true){
Socket s = ss.accept(); // 该方法是阻塞式的,除非得到连接,否则一则等待
// 把接收到的每一个Socket都存放在Vector中,以便后面使用
......
// 启动线程,进行处理
......
}
线程操作如下:
class SocketOpt extends Thread {
private Socket s;
// 初始化Socket
public SocketOpt(Socket s) {
this.s = s;
}
public void run() {
try {
DataInputStream dis = new DataInputStream(new BufferedInputStream(s.getInputStream()));
while(true) {
// 接收客户端发送的消息
String msg = dis.readUTF();
// 遍历集合中的Socket连接,转发消息
for(Socket socket:vector) {
// 如果不是当前的正在使用的Socket,那么就把消息转发出去
if(socket != s) {
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
dos.writeUTF(msg);
dos.flush();
}
}
// 退出循环
if(msg.equals("bye")) {
break;
}
}
} catch(Exception e) {
e.printStackTrace();
// 退出时,把它移出集合
vector.remove(s);
}
}
}