Socket编程分为服务端和客户端编程,最原生的实现方式是bio(同步阻塞模式)。这种方式的socket编程不能满足实际生产的需要,但作为入门的案例还是可以滴。
实现步骤
1 服务端:
package my.bio1;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author: Linchong
* @Date: 2018/7/10 13:34
* @Description:
*/
public class Server {
private static final int PORT = 8765;
public static void main(String[] args) {
ServerSocket server = null;
try {
server = new ServerSocket(PORT);
System.out.println("服务器已启动....");
while (true) {
//将server设置为阻塞状态,如果有客户端的连接请求就会产生一个socket
Socket socket = server.accept();
//当有客户端向服务器发送请求连接的时候就会创建一个线程处理请求
//ServerHandler1是处理请求的具体实现
new Thread(new ServerHandler1(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(server != null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2 服务端处理类
package my.bio1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* @author: Linchong
* @Date: 2018/7/10 13:36
* @Description:
*/
public class ServerHandler1 implements Runnable {
private Socket socket;
public ServerHandler1(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(),true);
String body = null;
int i = 1;
while(true) {
//获取客户端的请求消息
body = in.readLine();
System.out.println("Server:" +body);
//向客户端响应消息
out.println("服务器响应消息"+i++);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(out != null) {
out.close();
}
if(in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3 客户端
package my.bio1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* @author: Linchong
* @Date: 2018/7/10 13:40
* @Description:
*/
public class Client {
private static final String ADDRESS = "127.0.0.1";
private static final int PORT = 8765;
public static void main(String[] args) {
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(ADDRESS,PORT);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
//向服务端发送消息
out.println("收到客户端的请求1");
out.println("收到客户端的请求2");
out.println("收到客户端的请求3");
out.println("收到客户端的请求4");
String response = null;
//接收服务端的响应消息
while(true) {
response = in.readLine();
System.out.println("Client:"+response);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(out != null) {
out.close();
}
if(in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
总结
1.socket编程主要是关注服务端,服务端需要设定服务的端口号,将服务设置为等待客户端连接的状态,一旦有客户端请求连接,就通过TCP三次握手机制建立连接,连接成功就两端都会产生socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
2. 服务端通过ServerSocket产生server,客户端通过Socket产生socket
3. bio模式的缺点:
因为每次客户端请求都会启动一个线程去建立连接,而系统的线程上限是有限的(Windows上限一般为1000,Linux上限为2000),所以这种方式进行Socket通信很难实现高并发,系统性能会存在很大的瓶颈。