网络编程
Socket
IP和端口号
什么是IP
IP是根据TCP/IP协议划定,由32位二进制数组成,而且在因特网上是唯一的数值
例如:某台计算机,连上网的IP是:
11010101 01001001 11110000 11001100
为了便于记忆,会将这32位二进制数,每8位一组,每段之间用小数点分割
11010101.01001001.11110000.11001100
再将每八位转化为十进制
213.73.240.204
如何查看自己电脑的ip
-
按win+R, 输入cmd,打开dos窗口
-
在dos窗口输入ipconfig
什么是端口号
端口号(port number)就是计算机为了给每个网络程序分配一个独一无二的区别符,有了这些端口号,就可以准确定位到具体的程序。
端口号是个整数,范围0-65535,分为周知端口和动态端口
-
周知端口就是众所周知的端口,是端口号中的明星,本身的存在就是有自身用途,这些端口我们一般不使用,范围是0-1023。
-
动态端口,剩下的端口号都是动态端口,动态端口的意思就是将这些端口动态的分配给每个需要端口号的程序,当开启一个程序时,就分配给它一个端口
Socket概述
在计算机领域中,Socket也被称为套接字编程,它是计算机之间进行通信的一种约定或者说是一种方式。
应用程序可以通过它发送或者接收数据,可以对其发送过来的内容像处理文件一样,打开、关闭或者读写等操作,套接字允许应用程序将I/O插入到互联网上,并与网络中的其他程序进行通信。
Socket常用方法
服务器端ServerSocket
在服务器端选择一个端口号,然后在指定的端口号上等待客户端发起的连接
构造方法:
1 2 3
| ServerSocket(int port) 创建一个绑定特定端口号的服务器套接字 accept() 侦听并接受到发送到此套接字的连接 close() 关闭此套接
|
客户端Socket
构造方法:
1 2 3 4
| Socket(String host,int port) 创建一个套接字,并且连接到host,并且绑定端口号 close() 关闭此套接字 getInputStream() 返回此套接字的输入流 getOutputStram() 返回此套接字的输出流
|
聊天室
服务器端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
| package socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Scanner;
public class Server {
private ServerSocket server; private Collection<PrintWriter> allOut = new ArrayList<>(); public Server() { try { System.out.println("正在启动服务器..."); server = new ServerSocket(8088); System.out.println("服务器启动完毕!!!"); } catch (IOException e) { e.printStackTrace(); } } public void start() { try { while (true) { System.out.println("等待客户端链接...");
Socket socket = server.accept(); System.out.println("一个客户端链接了!!!"); ClientHandler handler = new ClientHandler(socket); Thread t = new Thread(handler); t.start(); } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { Server server = new Server(); server.start(); }
private class ClientHandler implements Runnable { private Socket socket; public ClientHandler(Socket socket) { this.socket = socket; } @Override public void run() { PrintWriter pw = null; try {
InputStream in = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr); OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8); BufferedWriter bw = new BufferedWriter(osw); pw = new PrintWriter(bw, true);
synchronized (Server.this) { allOut.add(pw); } sendMessage("有新的客户端上线了!当前在线人数:" + allOut.size()); String line; while ((line = br.readLine()) != null) { System.out.println("客户端说:" + line); sendMessage(line);
} } catch (IOException e) { e.printStackTrace(); } finally { synchronized (Server.this) {
allOut.remove(pw); } sendMessage("有客户端下线了!当前在线人数:" + allOut.size()); try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
private void sendMessage(String msg) { synchronized (Server.this){
for (PrintWriter pw : allOut) { pw.println(msg); } } } } }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| package socket; import java.io.*; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner;
public class Client {
private Socket socket;
public Client() { try { System.out.println("正在链接服务器...");
socket = new Socket("localhost", 8088); } catch (IOException e) { e.printStackTrace(); } }
public void start() { try { ServerHandler handler = new ServerHandler(); Thread t = new Thread(handler); t.setDaemon(true); t.start();
OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8); BufferedWriter bw = new BufferedWriter(osw); PrintWriter pw = new PrintWriter(bw, true); Scanner scanner = new Scanner(System.in); while (true) { String line = scanner.nextLine(); if ("exit".equalsIgnoreCase(line)) { break; } pw.println(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { Client client = new Client(); client.start(); }
private class ServerHandler implements Runnable { @Override public void run() { try { InputStream in = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr); String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { } } } }
|
测试
切记先运行服务器,后运行客户端!!!
**常见问题: **
表示端口被占用,解决方式:换个没有被占用的端口
表示连接被拒绝,因为服务器没启动,解决方式:先启动服务器,然后再启动客户端