1 概念
socket:网络编程
io流:在同一个电脑中实现 内存与硬盘上的文件之间的数据传输
socket:在网络中的两台电脑之间实现数据传输
ip
Internet Protocol:互联网传输协议
ip地址:互联网为每台电脑分配的一个用于唯一标识的字符串
ip分类:ipv4版本:4个1byte组成的字符串 格式:192.168.198.120
ipv6版本:8个2byte组成的字符串 格式:abcf.123a.234b.9876.1111.0.0.1.1
本地ip:localhost 、127.0.0.1
端口
port:逻辑:::逻辑端口
为电脑安装的所有软件分配的一个编号:0-65535
注意:10000一下的端口不要使用:::
socket
Transmission Control Protocol:是一种面向连接的(点对点)、可靠的、基于字节流的传输层通信协议
类似于:打固定电话
User Datagram Protocol:是一种无需连接的、不可靠的、基于报文流的传输层通信协议
类似于:发报机
2 TCP
客户端和服务器端
2.1 案例1
package day17_xml_socket;
public class Demo03TcpClient {
public static void main(String[] args)throws Exception {
Socket socket=new Socket(InetAddress.getByName("localhost"), 10086);
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
byte[] arr=new byte[1024];
int n=in.read(arr);
System.out.println("客户端接收到信息是:"+new String(arr, 0,n));
out.write("我是客户端!".getBytes());
System.out.println("客户端:getPort="+socket.getPort());
System.out.println("客户端:getInetAddress().getHostName()="+socket.getInetAddress().getHostName());
System.out.println("客户端:getLocalPort="+socket.getLocalPort());
System.out.println("客户端:getLocalAddress().getHostName()="+socket.getLocalAddress().getHostName());
socket.close();
}
}
package day17_xml_socket;
public class Demo03TcpServer {
public static void main(String[] args)throws Exception {
ServerSocket server=new ServerSocket(10086) ;
System.out.println("10086等待连接。。。。");
Socket socket=server.accept();
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
out.write("你是谁?".getBytes());
byte[] arr=new byte[1024];
int n=in.read(arr);
System.out.println("10086接收到信息是:"+new String(arr, 0,n));
System.out.println("服务器端:getPort="+socket.getPort());
System.out.println("服务器端:getInetAddress().getHostName()="+socket.getInetAddress().getHostName());
System.out.println("服务器端:getLocalPort="+socket.getLocalPort());
System.out.println("服务器端:getLocalAddress().getHostName()="+socket.getLocalAddress().getHostName());
server.close();
}
}
2.2 案例2:字符串转换
对客户端发送的信息 进行修改(大小写转换 删除数字) 后返回给客户端
package day18_socket;
...
public class ZuoYe01Client {
public static void main(String[] args) throws Exception{
BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
Socket socket=new Socket("localhost", 10086);
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
String clientIpPort=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String serverIpPort=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
while(true) {
String message=bin.readLine();
out.write(message.getBytes());
if(message.equals("%_886_%")) {
System.out.println(clientIpPort+"结束对话 发出了886!");
break;
}
byte[] arr=new byte[1024];
int n=in.read(arr);
System.out.println(clientIpPort+"接收到服务器("+serverIpPort+")的反馈:"+new String(arr, 0,n));
}
socket.close();
}
}
package day18_socket;
...
public class ZuoYe01Server {
public static void main(String[] args)throws Exception {
ServerSocket server=new ServerSocket(10086);
Socket socket=server.accept();
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
InputStreamReader ir=new InputStreamReader(in);
String serverIpPort=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String cilentIpPort=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
char[] arr=new char[1024];
int n;
while(true) {
n=ir.read(arr);
String line=new String(arr, 0,n);
if(line.equals("%_886_%")) {
System.out.println(serverIpPort+"与"+cilentIpPort+"的对话结束!");
break;
}
System.out.println(serverIpPort+"接收到"+cilentIpPort+"的信息:"+line);
line=change(line);
out.write(line.getBytes());
}
}
private static String change(String str) {
StringBuilder stb=new StringBuilder(str);
for (int i = 0; i <stb.length(); i++) {
char c=stb.charAt(i);
if(Character.isUpperCase(c)) {
stb.setCharAt(i, Character.toLowerCase(c));
}else if(Character.isLowerCase(c)) {
stb.setCharAt(i, Character.toUpperCase(c));
}else if(Character.isDigit(c)) {
stb.deleteCharAt(i);i--;
}
}
return stb.toString();
}
}
2.3 案例3:文件上传
package day18_socket;
...
public class ZuoYe02Client {
public static void main(String[] args) throws Exception{
Socket socket=new Socket("localhost",10086);
File file=new File("C:\\Users\\Administrator\\Desktop\\img\\0.jpeg");
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
String clientIpPort=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String serverIpPort=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
out.write(file.getName().getBytes());
FileInputStream fin=new FileInputStream(file);
byte[] arr=new byte[1024];
int n;
while((n=fin.read(arr))!=-1) {
out.write(arr, 0, n);
}
socket.shutdownOutput();
n=in.read(arr);
System.out.println("客户端接收到服务器的反馈信息:"+new String(arr,0,n));
socket.close();
fin.close();
}
}
package day18_socket;
...
public class ZuoYe02Server {
public static void main(String[] args) throws Exception{
ServerSocket server=new ServerSocket(10086);
Socket socket=server.accept();
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
String serverIpPort=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String clientIpPort=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
byte[] arr=new byte[1024];
int n=in.read(arr);
String fileName=new String(arr,0,n);
FileOutputStream fout=new FileOutputStream("src/day18_socket/"+fileName);
while(true) {
n=in.read(arr);
if(n==-1) {
out.write((clientIpPort+"你发送的文件"+fileName+":已接收完毕!").getBytes());
break;
}
fout.write(arr, 0, n);
}
socket.close();
fout.close();
}
}
2.4 案例4:文件夹上传
package day18_socket;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ZuoYe03Client {
static String pathYuanDir;
public static void main(String[] args) throws Exception{
File file=new File("C:\\Users\\Administrator\\Desktop\\java43课堂记录");
pathYuanDir=file.getParent();
System.out.println();
Socket socket=new Socket("localhost",10086);
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
sendFile(file,out);
socket.shutdownOutput();
byte[] arr=new byte[1024];
int n;
n=in.read(arr);
System.out.println("客户端接收到服务器的反馈信息:"+new String(arr,0,n));
socket.close();
}
private static void sendFile(File file,OutputStream out)throws Exception {
if(file.isFile()) {
String fileName=file.getAbsolutePath().replace(pathYuanDir+"\\", "");
System.out.println("文件:::="+fileName);
out.write(("%#@$!~file_"+fileName).getBytes());
FileInputStream fin=new FileInputStream(file);
byte[] arr=new byte[1024];
int n;
while((n=fin.read(arr))!=-1) {
out.write(arr, 0, n);
}
fin.close();
return ;
}
File[] zis=file.listFiles();
for (File zi : zis) {
sendFile(zi,out);
}
}
}
package day18_socket;
...
public class ZuoYe03Server {
public static void main(String[] args) throws Exception{
String muDiPath="C:\\Users\\Administrator\\Desktop\\aa";
ServerSocket server=new ServerSocket(10086);
Socket socket=server.accept();
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
String serverIpPort=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String clientIpPort=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
byte[] arr=new byte[1024];
int n;
FileOutputStream fout=null;
while((n=in.read(arr))!=-1) {
String line=new String(arr,0,n);
if(line.startsWith("%#@$!~file_")) {
if(fout!=null) {
fout.close();
}
line=line.replace("%#@$!~file_", "");
System.out.println("转换后的文件名:line="+line);
File file=new File(muDiPath,line);
File dir=file.getParentFile();
if(!dir.exists()) {
dir.mkdirs();
}
System.out.println("文件="+file.getAbsolutePath());
fout=new FileOutputStream(file);
}else {
fout.write(arr, 0, n);
}
}
out.write((clientIpPort+"你发送的文件夹:已接收完毕!").getBytes());
socket.close();
}
}
2.5 案例5:双方互发信息
双方互发信息 接收和发送互不干扰
class ReadThread extends Thread{
Socket socket;
private BufferedReader bin;
public ReadThread(Socket socket) {
this.socket=socket;
try {
bin=new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void run() {
String me=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String him=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
try {
while(true) {
String line=bin.readLine();
System.out.println(me+" 接收到 "+him+" 的信息:"+line);
if(line.equals("%886%")) {
System.out.println(him+"结束聊天!");
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class WriteThread extends Thread{
Socket socket;
private BufferedWriter bout;
public WriteThread(Socket socket) {
try {
bout=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void run() {
BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
try {
while(true) {
String line=bin.readLine();
bout.write(line);
bout.flush();
bout.newLine();
bout.flush();
if(line.equals("&886&")) {
break;
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Socket socket=new Socket("localhost",10086);
new ReadThread(socket).start();
new WriteThread(socket).start();
ServerSocket server=new ServerSocket(10086);
Socket socket=server.accept();
new ReadThread(socket).start();
new WriteThread(socket).start();
2.6 案例6:群聊
所有的客户端把信息发给服务器 服务器把接收的所有信息转发给所有的客户端
class WriteThread2Client extends Thread{
Socket socket;
private BufferedWriter bout;
public WriteThread2Client(Socket socket) {
try {
bout=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void run() {
BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
try {
while(true) {
String line=bin.readLine();
bout.write(line);
bout.flush();
bout.newLine();
bout.flush();
if(line.equals("&886&")) {
break;
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class ReadThread2Client extends Thread{
Socket socket;
private BufferedReader bin;
public ReadThread2Client(Socket socket) {
this.socket=socket;
try {
bin=new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void run() {
String me=socket.getLocalAddress().getHostAddress()+"_"+socket.getLocalPort();
String him=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
try {
while(true) {
String line=bin.readLine();
System.out.println(me+" 接收到 "+him+" 的信息:"+line);
if(line.equals("%886%")) {
System.out.println(him+"结束聊天!");
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
服务器需要给每个连接的客户端创建一个线程 用于给读取客户端交互
class SocketThread extends Thread{
Socket socket;
SocketThread(Socket socket){
this.socket=socket;
}
public void run() {
try {
BufferedReader bin=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String client=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
while(true) {
String line=bin.readLine();
line=client+"说:"+line;
for (BufferedWriter bout : MyChat02Server.outSet) {
bout.write(line);
bout.newLine();
bout.flush();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Socket socket=new Socket("localhost",10086,InetAddress.getByName("localhost"),50001);
new ReadThread2Client(socket).start();
new WriteThread2Client(socket).start();
Socket socket=new Socket("localhost",10086,InetAddress.getByName("localhost"),50002);
new ReadThread2Client(socket).start();
new WriteThread2Client(socket).start();
Socket socket=new Socket("localhost",10086,InetAddress.getByName("localhost"),50003);
new ReadThread2Client(socket).start();
new WriteThread2Client(socket).start();
public class MyChat02Server {
static Set<BufferedWriter> outSet=new HashSet<BufferedWriter>();
public static void main(String[] args) throws Exception{
ServerSocket server=new ServerSocket(10086);
while(true) {
Socket socket=server.accept();
outSet.add(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
new SocketThread(socket).start();
}
}
}
2.7 案例7:群聊+单聊
只需要更改服务器端即可:当接收道信息后 对学校进行解析 判断是群聊 还是单聊
如果以@@@@####开头 就是单聊 从中获取接收方的ip+port 然后把信息单独发给他
package day18_socket;
...
public class MyChat03Server {
static Map<String, BufferedWriter> ipOutMap=new HashMap<>();
public static void main(String[] args) throws Exception{
ServerSocket server=new ServerSocket(10086);
while(true) {
Socket socket=server.accept();
String client=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
ipOutMap.put(client,new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
new SocketThread3(socket).start();
}
}
}
class SocketThread3 extends Thread{
Socket socket;
SocketThread3(Socket socket){
this.socket=socket;
}
public void run() {
try {
BufferedReader bin=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String client=socket.getInetAddress().getHostAddress()+"_"+socket.getPort();
while(true) {
String line=bin.readLine();
if(line.equals("show me clients!")) {
BufferedWriter out=MyChat03Server.ipOutMap.get(client);
out.write(MyChat03Server.ipOutMap.keySet().toString());
out.newLine();
out.flush();
}else if(line.startsWith("@@@@####")) {
String ip_port=line.substring(8, line.indexOf(":"));
BufferedWriter out=MyChat03Server.ipOutMap.get(ip_port);
line=client+"私聊的信息:"+line.substring(line.indexOf(":")+1);
out.write(line);
out.newLine();
out.flush();
}else {
line=client+"说:"+line;
for (BufferedWriter bout : MyChat03Server.ipOutMap.values()) {
bout.write(line);
bout.newLine();
bout.flush();
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}