简介
套接字(socket) 是一个抽象层,应用程序可以通过它发送或接收数据,与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。
1.传输层实现端到端的通信,每一个传输层连接有两个端点,连接的端点叫做套接字(socket)
2.每个套接字都有一个套接字序号,包括主机的IP地址与一个16位的主机端口号,即(主机IP地址:端口号)
3.如何实现通信的?
~~~~~~ 通信时,一个网络应用程序将传输的信息写入本主机的socket中,该socket通过网络接口卡的传输介质将信息发送给另一台主机的socket中,使这段信息能传送到其他程序中
4.套接字也是基于TCP或者UDP的应用程序编程接口(API)
分类
流式套接字、数据报套接字和原始套接字。
(1)流式套接字。它提供了一种可靠的、面向连接的双向数据传输服务,实现了数据无差错、无重复的发送。
(2)数据报套接字。它提供了一种无连接、不可靠的双向数据传输服务。
(3)原始套接字。该套接字允许对较低层协议(如IP或ICMP)进行直接访问,常用于网络协议分析,检验新的网络协议实现,也可用于测试新配置或安装的网络设备。
调用流程
~~~~~~~~~~~~~~~~~~~~~~~~~
服务器
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
客户端
socket():创建套接字。
bind():指定本地地址(绑定端口号)。
connect():将套接字连接到目的地址。
listen():设置等待连接状态。
accept():接受连接请求。服务器调用accept进入等待状态,直到到达一个连接请求。
send()/recv()和sendto()/recvfrom():发送和接收数据 。
closesocket():关闭套接字。
UDP通信
服务端:
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8568);
while(true){
byte[] bytes = new byte[4096];
DatagramPacket receivePacket = new DatagramPacket(bytes,0,bytes.length);
socket.receive(receivePacket);
int len = receivePacket.getLength();
String message = new String(bytes,0,len,"UTF-8");
System.out.println("接收的数据:" + message);
String echoMessage = message;
System.out.println("发送的数据" +echoMessage);
byte[] sendBytes = echoMessage.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBytes,0,sendBytes.length,receivePacket.getAddress(),receivePacket.getPort());
socket.send(sendPacket);
//socket.close();
}
}
客户端:
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
Scanner scanner = new Scanner(System.in);
while(true){
String message = scanner.nextLine();
byte[] sendBuffer = message.getBytes("UTF-8");
InetAddress address = InetAddress.getLocalHost();
int port = 8568;
DatagramPacket senPacket = new DatagramPacket(sendBuffer,0,sendBuffer.length,address,port);
socket.send(senPacket);
byte[] receiveBuffer = new byte[4096];
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer,receiveBuffer.length);
socket.receive(receivePacket);
String echoMessage = new String(receiveBuffer,0,receivePacket.getLength());
System.out.println(echoMessage);
//socket.close();
}
}
TCP通信
服务端:
public class TCPServer {
public static class Worker implements Runnable{
public final Socket socket;
public Worker(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
try {
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
Scanner scanner = new Scanner(is,"UTF-8");
PrintWriter printWriter = new PrintWriter( new OutputStreamWriter(os,"UTF-8"),false);
while(scanner.hasNextLine()){
String message = scanner.nextLine();
System.out.println(name + "收到的消息:"+message);
String echoMessage = message;
System.out.println(name +"发送的消息:"+echoMessage);
printWriter.println(echoMessage);
printWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8088);
int count = 0;
while(true){
Socket socket = serverSocket.accept();
Thread thread = new Thread(new Worker(socket),"线程"+count++);
thread.start();
}
}
}
客户端:
public class TCPClient {
public static void main(String[] args) throws IOException {
Scanner userInput = new Scanner(System.in);
while(true){
String message = userInput.nextLine();
Socket socket = new Socket("127.0.0.1",8088);
//Socket socket = new Socket();
// socket.bind(new InetSocketAddress("",));
// socket.connect(new InetSocketAddress("1",8088));
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
byte[] sendBuffer = message.getBytes("UTF-8");
os.write(sendBuffer);
os.write('\r');
os.write('\n');
Scanner scanner = new Scanner(is,"UTF-8");
System.out.println(scanner.nextLine());
socket.close();
}
}
}