Socket也叫做套接字,相当于数据线两端的插头。Java Socket是实现Java网络编程的机制,其中服务器端的套接字成为ServerSocket,而客户端的套接字称为Socket。每一个Socket都由IP地址和端口号唯一确定。
Socket(套接字) 用于描述IP地址和端口,是一个通讯链的句柄,可以用来实现不同是的虚拟机或不同虚拟机或不同计算机之间的通讯。网络中的主机一般运行多个服务器,每个服务器上的每一种服务都会打开一个Socket并绑定一个端口,不同的端口对应着不同的服务。
根据连接启动的方式及本地套接字要连接的目标,套接字之间的连接可以分为服务器监听、客户端请求、连接确认三个步骤。
1.服务器监听
服务器端套接字只需要在程序启动之后处于等待连接的状态,并实时监听网络状态,等待其他客户端套接字的连接。
2.客户端请求
客户端的套接字需要先创建一个套接字,并在套接字中描述服务器套接字的信息(IP地址和端口号),让后向服务器套接字提出连接请求。
3.连接确认
当服务器端套接字监听到或接收到客户端套接字的连接请求时,就会响应客户端套接字的请求,建立一个新的线程,把服务器端的套接字描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,接收其他客户端套接字的连接请求。
TCP服务端
服务器端
public class SocketServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
run();
}
public static void run() {
// socket 指定的额端口号为0-65535,不能与其他进程端口冲突,否则启动时会报程序占用错误
int serverPort = 4700;
// 创建服务端Socket
ServerSocket serverSocket = null;
int recvMsgSize = 0;
// 接收字节缓冲数组
byte[] receivBuf = new byte[32];
try {
serverSocket = new ServerSocket(serverPort);
// 处理完一个客户端请求之后再进入等待状态
while (true) {
// 至此,程序一直等待客户端连接
System.out.println("服务端已经启动,绑定端口"+serverPort);
Socket clintSocket = serverSocket.accept();
SocketAddress clineAddress = clintSocket.getRemoteSocketAddress();
System.out.println("接收客户端连接,ip"+clineAddress);
//开启输入输出流
InputStream inputStream = clintSocket.getInputStream();
OutputStream outputStream = clintSocket.getOutputStream();
//接收客户端发送的数据,并原样返回给客户端
while ((recvMsgSize = inputStream.read(receivBuf)) != -1) {
String receivedDataString = new String(receivBuf.toString());
System.out.println(receivedDataString);
outputStream.write(receivBuf,0,recvMsgSize);
}
clintSocket.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
客户端
public class SocketClientDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String host = "127.0.0.1";
int port = 4700;
String sendMsg = "send data from client";
connect(host, port, sendMsg.getBytes());
}
public static void connect(String server,int serverPort,byte[] data) {
//创建socket对象,连接服务端socket
Socket socket = null;
try {
socket = new Socket(server,serverPort);
System.out.println("连接服务器并发送数据。。。");
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
outputStream.write(data);
//连接数据
//目前收到的总字节长度
int totalBytesRcvd = 0;
// 最后一次读取的字节长度
int bytesRvcd;
//将服务器返回消息读到data字符数组中
while (totalBytesRcvd < data.length) {
bytesRvcd = inputStream.read(data,totalBytesRcvd,data.length-totalBytesRcvd);
if (bytesRvcd == -1) {
throw new SocketException("连接中断中。。。。");
}
totalBytesRcvd += bytesRvcd;
}
System.out.println("接收的数据:" + new String(data));
} catch (Exception e) {
// TODO: handle exception
}finally {
try {
if (socket !=null) {
socket.close();
}
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}