通过三次握手建立连接
Step 1:客户主机发送TCP SYN数据段到服务器(SYN=1,客户机制定起始序号seq=x)
Step 2:服务器主机收到SYN,用SYN+ACK数据段响应(SYN=1,ACK=1,seq=y;ack=x+1)
Step 3:客户收到SYN+ACK,用ACK数据段响应,可以包含数据(SYN=0,ACK=1,seq=x+1,ack=y+1) (当SYN=1,ACK=0表明这是一个连接请求报文,对方若同意建立连接,则在响应报文中使用SYN=1,ACK=1。SYN=1表示这是一个连接请求或连接接收报文)
释放连接过程
Step 1:客户结束发送TCP FIN控制数据段到服务器(FIN=1,seq=u)
Step 2:服务器收到FIN,用ACK响应。(ACK=1,seq=v,ack=u+1)
Step 3:服务器发送FIN(FIN=1,ACK=1,seq=w,ack=u+1)
Step 4:客户收到FIN,发送ACK确认关闭(ACK=1,seq=u+1,ack=w+1)
实现客户端与服务器的交互。通过多线程实现端的Receive和Send独立
客户端
public class Cilent { public static void main(String[] args) throws UnknownHostException, IOException { //创建连接 Socket socket = new Socket("127.0.0.1",19999); //创建输入输出流 Scanner scan = new Scanner(System.in); PrintStream ps = new PrintStream(socket.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); new Receive(socket).start(); while(true) { //向服务器发送消息 ps.println("客户端:"+scan.next()); } } }服务器
public class Server { public static void main(String[] args) throws IOException { //创建连接 ServerSocket server = new ServerSocket(19999); Socket socket = server.accept(); //创建流 Scanner scan = new Scanner(System.in); PrintStream ps = new PrintStream(socket.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); new Receive(socket).start(); while(true) { //向客户端发送消息 ps.println("服务器:"+scan.next()); } } }接收线程
public class Receive extends Thread{ private BufferedReader br; public Receive(Socket socket) throws IOException { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } @Override public void run() { while(true) { String readLine = null; try { readLine = br.readLine(); } catch (IOException e) {} System.out.println(readLine); } } }
1.各客户端先与服务器建立连接
2.连接以后就启动线程
3.线程实现消息的接收与转发
客户端
public class Cilent { /** * 群聊 * 客户端发送一条消息,服务器将其内容转发给其他客户端 * */ public static void main(String[] args) throws UnknownHostException, IOException { //创建套接字 Socket socket = new Socket("127.0.0.1",19999); //创建流 Scanner scan = new Scanner(System.in); PrintStream ps = new PrintStream(socket.getOutputStream()); new Receive(socket).start(); //向服务器发送消息 while(true) { ps.println("客户端1:"+scan.next()); } } }服务器
public class Server { public static ConcurrentHashMap<String, Socket> map = new ConcurrentHashMap<>(); public static void main(String[] args) throws IOException { /** * * 群聊:多个客户端与服务器连接 * 客户端:创建接收线程(为了与发送不冲突),while(true)循环向服务器发送信息 * 服务器:与多个客户端连接,每accept一次,就存储ConcurrentHashMap一次,并启动一个线程 * 利用多线程转发(每条线程都在不停地接收该客户端发送的信息并转发) * */ ServerSocket server = new ServerSocket(19999); //获取其他客户端的IP,Socket.存入HashMap中, while(true) { Socket socket = server.accept(); String ip = socket.getInetAddress().getHostAddress(); map.put(ip, socket); new MyThread(socket).start(); } } } //利用多线程像其他客户端转发 class MyThread extends Thread{ private Socket socket; public MyThread(Socket socket) { this.socket=socket; } @Override public void run() { BufferedReader br=null; try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e1) { } //循环接收来自客户端的消息 while(true) { try { String readLine = br.readLine(); System.out.println(readLine); //转发 Set<Entry<String,Socket>> entrySet=Server.map.entrySet(); for(Entry<String, Socket> entry:entrySet) { String key = entry.getKey(); Socket value = entry.getValue(); if(!key.equals(socket.getInetAddress().getHostAddress())) { PrintStream ps = new PrintStream(value.getOutputStream()); ps.println(readLine); } } } catch (IOException e) { } } } }接收线程
public class Receive extends Thread{ private BufferedReader br; public Receive(Socket socket) throws IOException { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } @Override public void run() { while(true) { String readLine = null; try { readLine = br.readLine(); } catch (IOException e) {} System.out.println(readLine); } } }客户端1:
public class Client01 { public static void main(String[] args) throws SocketException { DatagramSocket socket = new DatagramSocket(19321); new SendThread(socket,"127.0.0.1",19999,"UDP1号").start(); new ReceiveThread(socket).start(); } }客户端2号:
public class Client02 { public static void main(String[] args) throws SocketException { DatagramSocket socket = new DatagramSocket(19999); new SendThread(socket,"127.0.0.1",19321,"UDP2号").start(); new ReceiveThread(socket).start(); } }发送线程
public class SendThread extends Thread{ private DatagramSocket socket; private String ip; private int port; private String name; public SendThread(DatagramSocket socket, String ip, int port, String name) { this.socket = socket; this.ip = ip; this.port = port; this.name = name; } @Override public void run() { Scanner scan = new Scanner(System.in); while(true) { byte[] b = (name+":"+scan.nextLine()).getBytes(); DatagramPacket p; try { p = new DatagramPacket(b, b.length,InetAddress.getByName(ip),port); socket.send(p); } catch (IOException e) { } } } }接收线程
public class ReceiveThread extends Thread{ private DatagramSocket socket; public ReceiveThread(DatagramSocket socket) { this.socket = socket; } @Override public void run() { while(true) { byte[] b = new byte[1024]; DatagramPacket p = new DatagramPacket(b, b.length); try { socket.receive(p); System.out.println(new String(b).trim()); } catch (IOException e) { } } } }
提供免费接口的网站www.bejson.com
简述浏览器访问一个网页的过程?
浏览器向服务器发出对该页面中所包含对象的HTTP请求报文;服务器接收请求并用包含这些对象的HTTP响应报文进行响应。