Socket
java.net.Socket
-
套接字 Socket封装了TCP协议的通讯细节,使得我们使用它就可以和服务端建立链接并
基于两条流的读写操作完成与远端计算机的交互。 我们可以把Socket想象为"电话"。 -
Socket提供的常用构造器:
Socket(String host,int port)
通过给定的IP地址与端口与远端计算机建立TCP链接。
参数1:远端计算机的IP地址信息
参数2:远端计算机打开的服务端口
我们通过IP可以找到网络上的该计算机,通过端口找到运行在该机器上的
服务端应用程序 -
Socket中非常重要的一个方法:
OutputStream getOutputStream()
该方法返回一个字节输出流,使用该流写出的字节会发送给远端链接的计算机 -
服务端进行TCP的挥手断开操作方法:
调用socket.close()
-
java.net.BindException: address already in use
原因:服务端申请的端口被系统其它程序占用了。
解决办法:
1:后期遇到该问题通常是重复启动了两次服务端导致的,需要杀死之前启动的
服务端进程
2:更换端口号
例子:简易聊天室
Client类:
package socket;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class Client {
private Socket socket;
public Client(){
try {
System.out.println("正在连接服务器...");
socket = new Socket("111.192.129.140",8088);
System.out.println("成功连接服务器...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
try {
System.out.println(socket.getInetAddress()+"进入聊天室:");
ServerHandler serverHandler = new ServerHandler();
Thread thread = new Thread(serverHandler);
thread.setDaemon(true);
thread.start();
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw,true);
while(true){
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
if("exit".equals(line)){
break;
}
pw.println(socket.getInetAddress()+"说:"+line);
}
} catch (IOException e) {
}finally {
try {
socket.close();
System.out.println("聊天结束");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
private class ServerHandler implements Runnable{
@Override
public void run() {
try {
InputStreamReader isr = new InputStreamReader(socket.getInputStream(),StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
}
}
}
}
Server类:
package socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
public class Server {
private ServerSocket serverSocket;
private Collection<PrintWriter> allOut = new ArrayList<>();
public Server() {
try {
System.out.println("正在启动服务器...");
serverSocket = new ServerSocket(8099);
System.out.println("启动成功,等待用户连接...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
while (true) {
try {
Socket socket = serverSocket.accept();
ClientHandler client = new ClientHandler(socket);
Thread thread = new Thread(client);
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
private class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
PrintWriter pw;
try {
InputStreamReader isr = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(osw);
pw = new PrintWriter(bw,true);
synchronized (allOut) {
allOut.add(pw);
}
System.out.println(socket.getInetAddress() + "已成功连接!" + "当前人数:" + allOut.size());
String line;
try {
while ((line = br.readLine()) != null) {
sendMessage(line);
}
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
synchronized (allOut) {
allOut.remove(pw);
}
System.out.println(socket.getInetAddress() + "已退出聊天室 " + "当前在线人数:" + allOut.size());
}
} catch (IOException e) {
}
}
private void sendMessage(String line){
System.out.println(socket.getInetAddress() + "说:" + line);
synchronized (allOut) {
for (PrintWriter p : allOut) {
p.println(socket.getInetAddress() + "说:" + line);
}
}
}
}
}