目录
一、socket简介
1.在本地进程间通信,可以用pid标识一个进程。但在网络上,pid可能会存在冲突,所以使用ip地址+协议+端口号唯一标识网络中的一个进程。
2.socket起源unix,而unix是遵从一切皆文件的哲学,socket是基于一种从打开到读和写,再到关闭的模式去实现的。
3.socket与TCP/IP协议没有必然的联系,只是使得程序员更方便的使用TCP/IP协议栈,对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。
Socket是操作系统对外开放的接口。
二、Socket通信流程
步骤:
1.服务端socket() : 服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket.
2.服务端bind():服务器为socket绑定ip地址和端口号
3.服务端listen():服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开
4.客户端socket():客户端创建socket
客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket。
客户端连接成功,向服务器发送连接状态信息
5.服务端accept():服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直到客户端返回连接信息后才返回,开始接收下一个客户端连接请求.
服务器accept方法返回,连接成功
6.客户端send():客户端向socket写入信息
7.服务端recv():服务器读取信息
8.客户端close():客户端关闭socket
9.服务端close():服务器端关闭socket
三、Socket网络通信例子
一个网络应用程序,客户端向服务器发送一个字符串,服务器收到该字符串后将其打印到命令行上,然后向客户端返回该字符串的长度,最后,客户端输出服务器端返回的该字符串的长度,使用 TCP 方式去实现。
在socket包中创建4个类
少了一个人UDPServer
1.服务端代码
public class TCPServer {
public static void main(String[] args) throws Exception{
//创建socket,并将socket绑定到65000端口
ServerSocket ss = new ServerSocket(65000);
//死循环,使得socket一直等待并处理客户端发送过来的请求
while(true){
//监听65000端口,直到客户端返回连接信息后才返回
Socket socket = ss.accept();
//获取客户端的请求信息后,启动一个新线程执行相关业务逻辑
new LengthCalculator(socket).start();
}
}
}
2.服务端业务处理线程代码
public class LengthCalculator extends Thread{
//socket为成员变量,来接收服务端socket实例
private Socket socket;
public LengthCalculator(Socket socket){
this.socket = socket;
}
// run()保存了所有的业务逻辑
public void run(){
try {
//获取socket的输出流
OutputStream os = socket.getOutputStream();
//获取socket的输入流
InputStream is = socket.getInputStream();
int ch = 0;
//buff用来读取输入的内容,存成byte数组,ch用来获取读取数组的字节数
byte[] buff = new byte[1024];
ch = is.read(buff);
//将接收流的byte数组转换成字符串,这里获取的内容是客户端发送过来的字节数组
String content = new String(buff,0,ch);
System.out.println(content);
//往输出流里写入获得的字符串的长度,回发给客户端
os.write(String.valueOf(content.length()).getBytes());
//一定要关闭输入输出流以及socket
is.close();
os.close();
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
3.客户端代码
public class TCPClient {
public static void main(String[] args) throws Exception{
//创建socket,并指定连接的是本机的端口号为65000的服务器socket
Socket socket = new Socket("127.0.0.1",65000);
//获取输出流
OutputStream os = socket.getOutputStream();
//获取输入流
InputStream is = socket.getInputStream();
// 将要传递给server的字符串参数转换称byte数组,并将数组写入到输出流中
os.write(new String("hello world").getBytes());
int ch = 0;
byte[] buff = new byte[1024];
// buff主要用来读取输入的内容,存成byte数组,ch主要用来获取读取数组的长度(与服务端作用相同)
ch = is.read(buff);
//将接收流的byte数组转换成字符串,这里是从服务端回发的字符串参数的长度
String content = new String(buff,0,ch);
System.out.println(content);
//一定要关闭输入输出流及socket
is.close();
os.close();
socket.close();
}
}
4.运行结果
服务端:
客户端:
5.流程总结
Server端先创建一个socket,指定好ip和port之后,在循环接收客户端发送的请求,获取了请求后就调用业务相关逻辑处理。
Client端创建一个socket连接服务端的ip和port,再通过输入流和输出流去往里面写值或者去获取服务端的回执信息,并且进行处理。
最后一定要关闭输入输出流和socket。
以上就是TCP通信的整个流程。