├── README.md ├── hw1 ├── 2052717-hw1-q1.doc ├── 2052717-hw1-q1.log ├── 2052717-hw1-q1.sh ├── 2052717-hw1-q2.doc ├── 2052717-hw1-q2.log ├── 2052717-hw1-q2.sh ├── 2052717-hw1-q3.doc ├── 2052717-hw1-q3.log ├── 2052717-hw1-q3.sh ├── 2052717-hw1-q4.doc ├── 2052717-hw1-q4.log └── 2052717-hw1-q4.sh ├── hw2 ├── q1 │ ├── 2052717-hw2-q1-screen.doc │ └── 2052717-hw2-q1-src&run │ │ ├── Jump.java │ │ └── readme.md └── q2 │ ├── 2052717-hw2-q2-screen.doc │ └── 2052717-hw2-q2-src&run │ ├── Client │ ├── CgetClient.java │ ├── Check.java │ ├── CputClient.java │ ├── DownloadClient.java │ ├── Main.java │ ├── UploadClient.java │ └── readme.md │ └── Server │ ├── DownloadServer.java │ ├── DownloadServerThread.java │ ├── ServerThread.java │ ├── UploadServer.java │ └── readme.md ├── 期末作业.pdf ├── 期末项目 ├── 作业1-报告.pdf ├── 作业1-项目源码 │ ├── .idea │ │ ├── .gitignore │ │ ├── artifacts │ │ │ └── dblp_q1_jar.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ ├── uiDesigner.xml │ │ └── vcs.xml │ ├── dblp_q1.iml │ ├── out │ │ ├── artifacts │ │ │ └── dblp_q1_jar │ │ │ │ └── dataServer.jar │ │ └── production │ │ │ └── dblp_q1 │ │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ │ └── com │ │ │ └── app │ │ │ ├── client │ │ │ ├── Main.class │ │ │ ├── RequestClient$RunnableSearch.class │ │ │ └── RequestClient.class │ │ │ ├── common │ │ │ └── ServerInfo.class │ │ │ ├── datanode │ │ │ ├── DataNode.class │ │ │ ├── UploadClient.class │ │ │ └── XmlPreprocess.py │ │ │ └── server │ │ │ ├── DataServer.class │ │ │ ├── Query$RunnableQuery.class │ │ │ ├── Query.class │ │ │ ├── QueryServer.class │ │ │ ├── UploadServerThread.class │ │ │ ├── files │ │ │ ├── 1-0.xml │ │ │ └── 2-1.xml │ │ │ └── test.xml │ └── src │ │ ├── META-INF │ │ └── MANIFEST.MF │ │ └── com │ │ └── app │ │ ├── client │ │ ├── Logger.java │ │ ├── Main.java │ │ └── RequestClient.java │ │ ├── common │ │ └── ServerInfo.java │ │ ├── datanode │ │ ├── DataNode.java │ │ ├── UploadClient.java │ │ └── XmlPreprocess.py │ │ └── server │ │ ├── DataServer.java │ │ ├── Query.java │ │ ├── QueryServer.java │ │ ├── UploadServerThread.java │ │ └── test.xml ├── 作业2-报告.pdf └── 作业2-项目源码 │ ├── .idea │ ├── .gitignore │ ├── misc.xml │ ├── modules.xml │ ├── uiDesigner.xml │ └── vcs.xml │ ├── dblp_q2.iml │ ├── out │ └── production │ │ └── dblp_q2 │ │ └── com │ │ └── app │ │ ├── client │ │ ├── QueryClient$queryThread.class │ │ └── QueryClient.class │ │ ├── common │ │ └── ServerInfo.class │ │ ├── entity │ │ ├── Logger.class │ │ ├── Main.class │ │ ├── MemberList$MemberInfo.class │ │ ├── MemberList.class │ │ └── ServerNode.class │ │ └── server │ │ ├── 1.15.100.12.log │ │ ├── CommonServer.class │ │ ├── Daemon$ReceiveBeating.class │ │ ├── Daemon$SendBeating.class │ │ ├── Daemon$gossiping.class │ │ ├── Daemon$listentoIntroducer.class │ │ ├── Daemon.class │ │ ├── Introducer$ReceiveChange.class │ │ ├── Introducer$RunnableBroadCast.class │ │ ├── Introducer.class │ │ └── Query.class │ └── src │ └── com │ └── app │ ├── client │ └── QueryClient.java │ ├── common │ └── ServerInfo.java │ ├── entity │ ├── Logger.java │ └── MemberList.java │ └── server │ ├── CommonServer.java │ ├── Daemon.java │ ├── Introducer.java │ └── Query.java ├── 编程作业1.pdf └── 编程作业2.pdf /README.md: -------------------------------------------------------------------------------- 1 | # Distributed-System 2 | 2022年秋同济大学软件学院-分布式系统课程项目 3 | 4 | 水平有限,谨慎参考... 5 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q1.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/hw1/2052717-hw1-q1.doc -------------------------------------------------------------------------------- /hw1/2052717-hw1-q1.log: -------------------------------------------------------------------------------- 1 | 1060 2 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sum=0 3 | is_prime=1 4 | A="2052717" 5 | for ((i=0;i<=100;i++)); 6 | do 7 | if [[ $i -eq 0 || $i -eq 1 ]];then 8 | continue 9 | fi 10 | 11 | if [[ $i -eq 2 ]]; then 12 | let sum=$sum+$i 13 | continue 14 | fi 15 | 16 | for ((j=3;j2052717-hw1-q1.log 43 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q2.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/hw1/2052717-hw1-q2.doc -------------------------------------------------------------------------------- /hw1/2052717-hw1-q2.log: -------------------------------------------------------------------------------- 1 | 06:34:22 up 3:31, 1 user, load average: 0.00, 0.04, 0.01 2 | 06:34:32 up 3:31, 1 user, load average: 0.00, 0.04, 0.01 3 | 06:34:42 up 3:31, 1 user, load average: 0.07, 0.06, 0.01 4 | 06:34:52 up 3:31, 1 user, load average: 0.06, 0.05, 0.01 5 | 06:35:02 up 3:31, 1 user, load average: 0.05, 0.05, 0.01 6 | 06:35:12 up 3:32, 1 user, load average: 0.04, 0.05, 0.01 7 | 06:35:22 up 3:32, 1 user, load average: 0.04, 0.05, 0.01 8 | 06:35:32 up 3:32, 1 user, load average: 0.03, 0.05, 0.01 9 | 06:35:42 up 3:32, 1 user, load average: 0.03, 0.04, 0.01 10 | 06:35:52 up 3:32, 1 user, load average: 0.02, 0.04, 0.01 11 | 06:36:02 up 3:32, 1 user, load average: 0.02, 0.04, 0.01 12 | 06:36:12 up 3:33, 1 user, load average: 0.01, 0.04, 0.01 13 | 06:36:23 up 3:33, 1 user, load average: 0.01, 0.04, 0.00 14 | 06:36:33 up 3:33, 1 user, load average: 0.01, 0.03, 0.00 15 | 06:36:43 up 3:33, 1 user, load average: 0.08, 0.05, 0.01 16 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | uptime 3 | uptime>2052717-hw1-q2.log 4 | 5 | for ((i=1;i<15;i++)); 6 | do 7 | sleep 10 8 | uptime 9 | uptime>>2052717-hw1-q2.log 10 | done -------------------------------------------------------------------------------- /hw1/2052717-hw1-q3.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/hw1/2052717-hw1-q3.doc -------------------------------------------------------------------------------- /hw1/2052717-hw1-q3.log: -------------------------------------------------------------------------------- 1 | 15 2 | 915 3 | 141 seconds 4 | 0.0313333 0.0446667 0.00866667 5 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | wc -l $1 | awk '{print $1}' 3 | wc -l $1 | awk '{print $1}'>2052717-hw1-q3.log # 总行数 4 | rownum=`wc -l $1 | awk '{print $1}'` 5 | wc -m $1 | awk '{print $1}' 6 | wc -m $1 | awk '{print $1}'>>2052717-hw1-q3.log # 总字符数 7 | 8 | line1=`cat -n $1 | head -n 1` 9 | line2=`cat -n $1 | tail -n 1` 10 | 11 | line1=${line1% up*} 12 | line1=${line1##* } 13 | line2=${line2% up*} 14 | line2=${line2##* } 15 | 16 | # 时间差 17 | time=$(($(date +%s -d $line2) - $(date +%s -d $line1))); 18 | echo $time seconds>>2052717-hw1-q3.log 19 | echo $time seconds 20 | 21 | # 求平均 22 | sum1=0.00 23 | sum2=0.00 24 | sum3=0.00 25 | 26 | for ((i=1;i<=$rownum;i++)); 27 | do 28 | line=`cat -n $1 | head -n $i` 29 | num1=${line:0-16:4} 30 | num2=${line:0-10:4} 31 | num3=${line:0-4:4} 32 | 33 | sum1=`awk 'BEGIN{print "'$sum1'" + "'$num1'"}'` 34 | sum2=`awk 'BEGIN{print "'$sum2'" + "'$num2'"}'` 35 | sum3=`awk 'BEGIN{print "'$sum3'" + "'$num3'"}'` 36 | 37 | done 38 | 39 | avg1=`awk 'BEGIN{print "'$sum1'" / "'$rownum'"}'` 40 | avg2=`awk 'BEGIN{print "'$sum2'" / "'$rownum'"}'` 41 | avg3=`awk 'BEGIN{print "'$sum3'" / "'$rownum'"}'` 42 | 43 | # 格式化输出 44 | # avg1=`awk 'GEGIN{printf("%.2f",'$sum1' / '$rownum')}'` 45 | # avg2=`awk 'GEGIN{printf("%.2f",'$sum2' / '$rownum')}'` 46 | # avg3=`awk 'GEGIN{printf("%.2f",'$sum3' / '$rownum')}'` 47 | 48 | echo $avg1 $avg2 $avg3 49 | echo $avg1 $avg2 $avg3>>2052717-hw1-q3.log 50 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q4.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/hw1/2052717-hw1-q4.doc -------------------------------------------------------------------------------- /hw1/2052717-hw1-q4.log: -------------------------------------------------------------------------------- 1 | 32 2 | 22 3 | 12 4 | 2 5 | -------------------------------------------------------------------------------- /hw1/2052717-hw1-q4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | n=$1 3 | let count=1 4 | echo $n 5 | sleep 1 6 | # echo $count sec 7 | for ((i=$n-1;i>0;i--)); 8 | do 9 | let ok=$[count%10] 10 | if test $ok -eq 0 11 | then 12 | echo $i 13 | fi 14 | sleep 1 15 | let count=$count+1 16 | # echo $count sec 17 | done 18 | 19 | let ok=$[count%10] 20 | if test $ok -eq 0 21 | then 22 | echo $i 23 | fi -------------------------------------------------------------------------------- /hw2/q1/2052717-hw2-q1-screen.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/hw2/q1/2052717-hw2-q1-screen.doc -------------------------------------------------------------------------------- /hw2/q1/2052717-hw2-q1-src&run/Jump.java: -------------------------------------------------------------------------------- 1 | import javax.net.ssl.SSLSocket; 2 | import javax.net.ssl.SSLSocketFactory; 3 | import java.io.*; 4 | import java.net.InetAddress; 5 | import java.net.Socket; 6 | import java.net.URL; 7 | import java.nio.CharBuffer; 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Objects; 13 | import java.util.Set; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | import java.io.BufferedReader; 17 | import java.io.InputStreamReader; 18 | import javax.swing.*; 19 | import javax.xml.ws.Response; 20 | 21 | public class Jump { 22 | 23 | static String startSite="https://www.mit.edu"; 24 | 25 | public static int statNum=0; 26 | 27 | public static int edgeNum=0; 28 | 29 | public static HashMap map=new HashMap<>();//记录终点及其入度 30 | 31 | public static void getMaxInDegree(){ 32 | Set set=map.keySet(); 33 | map.entrySet(); 34 | List> list = new ArrayList(map.entrySet()); 35 | Collections.sort(list, (o1, o2) -> (o2.getValue() - o1.getValue()));//升序 36 | int maxv=list.get(0).getValue(); 37 | System.out.println(list.get(0).getKey()+"具有最大入度"+maxv); 38 | 39 | for(int i=1;i getList(final String s) { 102 | 103 | Pattern p=Pattern.compile(""); 104 | Matcher ma=p.matcher(s); 105 | final List list =new ArrayList(); 106 | while(ma.find()){ 107 | list.add(ma.group()); 108 | } 109 | 110 | Pattern p1=Pattern.compile("\"http(.*?)\"");//获取 111 | Matcher ma1= p1.matcher(list.toString()); 112 | final List list1 = new ArrayList(); 113 | while (ma1.find()){ 114 | list1.add(ma1.group()); 115 | } 116 | 117 | final List list2 = new ArrayList(); 118 | Pattern p2=Pattern.compile("\"(.*?)\""); 119 | Matcher ma2= p2.matcher(list1.toString()); 120 | while (ma2.find()){ 121 | list2.add(ma2.group(1)); 122 | } 123 | 124 | return list2; 125 | } 126 | 127 | //解析出html中的所有超链接,通过检查一级域名是否匹配筛选出外部url 128 | public static List parser(String strServer,String filename) throws IOException { 129 | // Pattern pm= Pattern.compile(RE_TOP_3 , Pattern.CASE_INSENSITIVE); 130 | // String filename=getTopDomain(strServer,pm); 131 | // System.out.println("126 read: "+filename+" "+strServer); 132 | File file = new File(filename);//定义一个file对象,用来初始化FileReader 133 | FileReader reader = new FileReader(file);//定义一个fileReader对象,用来初始化BufferedReader 134 | BufferedReader bReader = new BufferedReader(reader);//new一个BufferedReader对象,将文件内容读取到缓存 135 | StringBuilder sb = new StringBuilder();//定义一个字符串缓存,将字符串存放缓存中 136 | String s = ""; 137 | while ((s =bReader.readLine()) != null) {//逐行读取文件内容,不读取换行符和末尾的空格 138 | sb.append(s + "\n");//将读取的字符串添加换行符后累加存放在缓存中 139 | } 140 | bReader.close(); 141 | String str = sb.toString(); 142 | List list=getList(str); 143 | 144 | List retList=new ArrayList(); 145 | 146 | //记录该url的历史访问,确保一个url不会对一个外部链接重复访问两次 147 | List histVis = new ArrayList(); 148 | 149 | for (String link:list){ 150 | 151 | Pattern pattern= Pattern.compile(RE_TOP , Pattern.CASE_INSENSITIVE); 152 | String originDomain=getTopDomain(strServer,pattern); 153 | String linkDomain=getTopDomain(link,pattern); 154 | 155 | if (!Objects.equals(originDomain, linkDomain)&& !histVis.contains(link)) { 156 | //是外部域名且和初始网址不相同,可以访问 157 | histVis.add(link); 158 | retList.add(link); 159 | // System.out.println("add link "+link); 160 | } 161 | } 162 | 163 | return retList; 164 | } 165 | 166 | //递归访问所有的外部url 167 | public static void recursive(List urls,int jumpNum,String strServer) throws IOException { 168 | 169 | int count=0; 170 | 171 | if(jumpNum>4) return;//最多四跳 172 | 173 | for (String str:urls){ 174 | 175 | if(count>=6) return;//最多6个外部url 176 | 177 | else count++; 178 | 179 | System.out.println(++statNum+": "+strServer+"-->"+str);//计数君 180 | 181 | edgeNum++; 182 | 183 | if(!map.containsKey(str)) map.put(str,1); 184 | else map.put(str,map.get(str)+1); 185 | 186 | String filename=buildConnect(str); 187 | 188 | List retList=parser(str,filename);//retList包含所有外部url 189 | 190 | recursive(retList,jumpNum+1,str); 191 | 192 | } 193 | } 194 | 195 | public static void main(String []args) throws IOException { 196 | long startTime = System.currentTimeMillis(); 197 | //初始网页 198 | String strServer=startSite; 199 | 200 | // histVis.add(strServer); 201 | 202 | String filename=buildConnect(strServer); 203 | 204 | List retList=parser(strServer,filename);//retList包含所有外部url 205 | 206 | recursive(retList,1,strServer); 207 | long endTime=System.currentTimeMillis(); 208 | double usedTime=1.0*(endTime-startTime)/1000.0; 209 | 210 | System.out.println("边数:"+edgeNum+""); 211 | System.out.println("结点数:"+map.size()+""); 212 | System.out.println("总用时:"+usedTime+"s"); 213 | getMaxInDegree(); 214 | 215 | } 216 | } 217 | 218 | -------------------------------------------------------------------------------- /hw2/q1/2052717-hw2-q1-src&run/readme.md: -------------------------------------------------------------------------------- 1 | 修改Jump.java中的起始网址,运行即可。 -------------------------------------------------------------------------------- /hw2/q2/2052717-hw2-q2-screen.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/hw2/q2/2052717-hw2-q2-screen.doc -------------------------------------------------------------------------------- /hw2/q2/2052717-hw2-q2-src&run/Client/CgetClient.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.lang.reflect.Executable; 3 | import java.net.InetAddress; 4 | import java.net.Socket; 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Scanner; 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.Executors; 11 | 12 | import javax.imageio.stream.FileCacheImageOutputStream; 13 | 14 | public class CgetClient { 15 | static String filewithoutPath=""; 16 | 17 | public CgetClient(String name){ 18 | filewithoutPath=name; 19 | } 20 | public static void mergeFile() throws IOException { 21 | //块文件目录 22 | String chunkFileFolderPath = "src/downloads/"; 23 | //块文件目录对象 24 | File chunkFileFolder = new File(chunkFileFolderPath); 25 | //块文件列表 26 | File[] files = chunkFileFolder.listFiles(); 27 | //将块文件排序,按名称升序 28 | List fileList = Arrays.asList(files); 29 | Collections.sort(fileList, (o1, o2) -> { 30 | int len1=o1.getName().length(); 31 | int len2=o2.getName().length(); 32 | if (len1!=len2) { 33 | if(len1>len2) return 1; 34 | else return -1; 35 | } 36 | else { 37 | if(o1.getName().compareTo(o2.getName())>0) return 1; 38 | else return -1; 39 | } 40 | 41 | }); 42 | // System.out.println(fileList); 43 | 44 | //合并文件 45 | // System.out.println(chunkFileFolderPath); 46 | File mergeFile = new File("src/download_"+filewithoutPath); 47 | //创建新文件 48 | boolean newFile = mergeFile.createNewFile(); 49 | 50 | //创建写对象 51 | RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw"); 52 | 53 | byte[] b = new byte[1024]; 54 | for (File chunkFile : fileList) { 55 | //创建一个读块文件的对象 56 | RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "r"); 57 | int len = -1; 58 | while ((len = raf_read.read(b)) != -1) { 59 | raf_write.write(b, 0, len); 60 | } 61 | raf_read.close(); 62 | } 63 | raf_write.close(); 64 | } 65 | 66 | public static int getFileLineNum(String filePath) { 67 | try (LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(filePath))){ 68 | lineNumberReader.skip(Long.MAX_VALUE); 69 | int lineNumber = lineNumberReader.getLineNumber(); 70 | return lineNumber ;//实际上是读取换行符数量,写文本文件的时候是每行输出一个\n 71 | } catch (IOException e) { 72 | return -1; 73 | } 74 | } 75 | public void main() throws IOException { 76 | 77 | // String host1 =""; 78 | // String host2="192.168.56.104"; 79 | String host=""; 80 | 81 | // Scanner sc = new Scanner(System.in); 82 | // System.out.println("请输入您想下载的文件名称:");//lin.jpg 83 | 84 | // filewithoutPath=sc.next(); 85 | String filename = "src/map/map_"+filewithoutPath+".txt"; 86 | 87 | int lineNum=getFileLineNum(filename); 88 | System.out.println("块数"+lineNum); 89 | 90 | String progfilename = "src/downloadProg/prog_"+filewithoutPath+".txt"; 91 | int downloadfileNum=getFileLineNum(progfilename); 92 | 93 | String line; 94 | InputStream fis = new FileInputStream(filename); 95 | InputStreamReader isr = new InputStreamReader(fis); 96 | BufferedReader br = new BufferedReader(isr); 97 | 98 | File progFile=new File("src/downloadProg/prog_"+filewithoutPath+".txt"); 99 | BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(progFile,true))); 100 | 101 | int runCnt=0; 102 | try { 103 | 104 | while ((line = br.readLine()) != null) { 105 | 106 | if(++runCnt<=downloadfileNum) continue; 107 | 108 | // Do your thing with line 109 | // System.out.println(line); 110 | String[] words = line.split(" "); 111 | System.out.println("从服务器"+words[1]+"下载"); 112 | 113 | filename=words[0];//切换成块文件名称 114 | host=words[1]; 115 | 116 | 117 | Socket socket = new Socket(InetAddress.getByName(host),20527); 118 | System.out.println("成功连接到服务器: "+host); 119 | 120 | //给服务器发送文件名 121 | DataOutputStream outputStream = new DataOutputStream (socket.getOutputStream()); 122 | outputStream.writeUTF(filename); 123 | 124 | System.out.println("请求文件: " + filename); 125 | 126 | // ExecutorService exec=Executors.newCachedThreadPool(); 127 | // exec.execute(new Thread(new ClientThread(socket,filename))); 128 | 129 | //接收服务器的回应 130 | InputStream inputStream = socket.getInputStream(); 131 | //开辟本地文件的输出流,以存放从客户端发来的文件 132 | BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/downloads/" + filename )); 133 | byte[] data = new byte[1024]; 134 | int len = 0; 135 | while ( (len = inputStream.read(data)) != -1 ) { 136 | bos.write(data, 0, len); 137 | } 138 | System.out.println("文件已成功接收!"); 139 | 140 | inputStream.close(); 141 | outputStream.close(); 142 | bos.close(); 143 | socket.close(); 144 | bw.write(filename+"\n"); 145 | bw.flush(); 146 | 147 | } 148 | 149 | 150 | }catch(Exception e){ 151 | e.printStackTrace(); 152 | bw.close(); 153 | return; 154 | } 155 | 156 | bw.close(); 157 | mergeFile(); 158 | } 159 | } -------------------------------------------------------------------------------- /hw2/q2/2052717-hw2-q2-src&run/Client/Check.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.File; 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.RandomAccessFile; 7 | import java.net.Socket; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.HashMap; 12 | import java.util.Iterator; 13 | import java.util.List; 14 | 15 | public class Check { 16 | 17 | static String host1="192.168.56.102"; 18 | static String host2="192.168.56.104"; 19 | static int port=20527; 20 | 21 | 22 | public void main() throws IOException{ 23 | System.out.println("文件分块存储情况:"); 24 | String FileFolderPath = "src/map/"; 25 | //块文件目录对象 26 | File FileFolder = new File(FileFolderPath); 27 | //块文件列表 28 | File[] files = FileFolder.listFiles(); 29 | //将块文件排序,按名称升序 30 | List fileList = Arrays.asList(files); 31 | 32 | System.out.println(fileList); 33 | 34 | byte[] b = new byte[1024]; 35 | 36 | 37 | 38 | for (File file : fileList) { 39 | int chunkNum1=0; 40 | int chunkNum2=0; 41 | List chunkOrderList=new ArrayList(); 42 | //创建一个读块文件的对象 43 | HashMap map=new HashMap(); 44 | String filename=file.getName(); 45 | filename=filename.substring(4,filename.length()-4); 46 | System.out.println("对应文件:"+filename); 47 | FileInputStream inputStream = new FileInputStream(file); 48 | BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); 49 | 50 | String s=null; 51 | while ((s=br.readLine()) != null) { 52 | String []info=s.split(" "); 53 | map.put(info[0],info[1]); 54 | if(info[1].equals(host1)) chunkNum1++; 55 | else if(info[1].equals(host2)) chunkNum2++; 56 | chunkOrderList.add(info[0]); 57 | } 58 | inputStream.close(); 59 | br.close(); 60 | 61 | System.out.println(host1+"包含的该文件数据块个数:"+chunkNum1); 62 | System.out.println(host2+"包含的该文件数据块个数:"+chunkNum2); 63 | Collections.sort(chunkOrderList, (o1, o2) -> { 64 | int len1=o1.length(); 65 | int len2=o2.length(); 66 | if (len1!=len2) { 67 | if(len1>len2) return 1; 68 | else return -1; 69 | } 70 | else { 71 | if(o1.compareTo(o2)>0) return 1; 72 | else return -1; 73 | } 74 | 75 | }); 76 | System.out.println("块文件升序id序列:"+chunkOrderList); 77 | 78 | System.out.println("该文件数据块的所在服务器地址:"); 79 | Iterator it = map.keySet().iterator(); 80 | while (it.hasNext()) { 81 | 82 | // 遍历 Map 83 | String key = (String) it.next(); 84 | String val = (String) map.get(key); 85 | System.out.println("块文件名:" + key + ",服务器:" + val); 86 | } 87 | System.out.println("-----------------------------------------"); 88 | } 89 | 90 | 91 | System.out.println("服务器连通情况:"); 92 | try{ 93 | Socket socket = new Socket(host1,port); 94 | System.out.println(host1+"可以连通!"); 95 | socket.close(); 96 | }catch(Exception e){ 97 | // e.printStackTrace(System.out); 98 | System.out.println(host1+"无法连通!"); 99 | } 100 | 101 | try{ 102 | Socket socket = new Socket(host2,port); 103 | System.out.println(host2+"可以连通!"); 104 | socket.close(); 105 | }catch(Exception e){ 106 | // e.printStackTrace(System.out); 107 | System.out.println(host2+"无法连通!"); 108 | } 109 | } 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /hw2/q2/2052717-hw2-q2-src&run/Client/CputClient.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.net.Socket; 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.Random; 6 | 7 | public class CputClient { 8 | 9 | static String filename="";//文件名 10 | static long chunkFileNum=0; 11 | // static String chunkname=""; 12 | static String filewithoutPath=""; 13 | 14 | public CputClient(String name){ 15 | filename="src/"+name; 16 | filewithoutPath=name; 17 | } 18 | 19 | public static HashMap table = new HashMap<>(); 20 | public static int getFileLineNum(String filePath) { 21 | try (LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(filePath))){ 22 | lineNumberReader.skip(Long.MAX_VALUE); 23 | int lineNumber = lineNumberReader.getLineNumber(); 24 | return lineNumber ;//实际上是读取换行符数量,写文本文件的时候是每行输出一个\n 25 | } catch (IOException e) { 26 | return -1; 27 | } 28 | } 29 | 30 | 31 | public static void uploadClient() throws IOException{ 32 | String host1="192.168.56.102"; 33 | String host2 = "192.168.56.104"; 34 | String host =""; 35 | int port = 20527; 36 | 37 | String mapfilename = "src/map/map_"+filewithoutPath+".txt"; 38 | int chunkFileNum=getFileLineNum(mapfilename); 39 | 40 | String progfilename = "src/uploadProg/prog_"+filewithoutPath+".txt"; 41 | int uploadfileNum=getFileLineNum(progfilename); 42 | 43 | 44 | File progFile=new File("src/uploadProg/prog_"+filewithoutPath+".txt"); 45 | BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(progFile,true))); 46 | 47 | for (int i=uploadfileNum;i fileList = Arrays.asList(files); 29 | Collections.sort(fileList, (o1, o2) -> { 30 | int len1=o1.getName().length(); 31 | int len2=o2.getName().length(); 32 | if (len1!=len2) { 33 | if(len1>len2) return 1; 34 | else return -1; 35 | } 36 | else { 37 | if(o1.getName().compareTo(o2.getName())>0) return 1; 38 | else return -1; 39 | } 40 | 41 | }); 42 | // System.out.println(fileList); 43 | 44 | //合并文件 45 | // System.out.println(chunkFileFolderPath); 46 | File mergeFile = new File("src/download_"+filewithoutPath); 47 | //创建新文件 48 | boolean newFile = mergeFile.createNewFile(); 49 | 50 | //创建写对象 51 | RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw"); 52 | 53 | byte[] b = new byte[1024]; 54 | for (File chunkFile : fileList) { 55 | //创建一个读块文件的对象 56 | RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "r"); 57 | int len = -1; 58 | while ((len = raf_read.read(b)) != -1) { 59 | raf_write.write(b, 0, len); 60 | } 61 | raf_read.close(); 62 | } 63 | raf_write.close(); 64 | } 65 | 66 | public static int getFileLineNum(String filePath) { 67 | try (LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(filePath))){ 68 | lineNumberReader.skip(Long.MAX_VALUE); 69 | int lineNumber = lineNumberReader.getLineNumber(); 70 | return lineNumber ;//实际上是读取换行符数量,写文本文件的时候是每行输出一个\n 71 | } catch (IOException e) { 72 | return -1; 73 | } 74 | } 75 | public void main() throws IOException { 76 | 77 | // String host1 =""; 78 | // String host2="192.168.56.104"; 79 | String host=""; 80 | 81 | // Scanner sc = new Scanner(System.in); 82 | // System.out.println("请输入您想下载的文件名称:");//lin.jpg 83 | 84 | // filewithoutPath=sc.next(); 85 | String filename = "src/map/map_"+filewithoutPath+".txt"; 86 | 87 | int lineNum=getFileLineNum(filename); 88 | System.out.println("块数"+lineNum); 89 | 90 | String line; 91 | InputStream fis = new FileInputStream(filename); 92 | InputStreamReader isr = new InputStreamReader(fis); 93 | BufferedReader br = new BufferedReader(isr); 94 | 95 | File progFile=new File("src/downloadProg/prog_"+filewithoutPath+".txt"); 96 | BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(progFile,true))); 97 | 98 | try { 99 | 100 | while ((line = br.readLine()) != null) { 101 | 102 | // Do your thing with line 103 | // System.out.println(line); 104 | String[] words = line.split(" "); 105 | System.out.println("从服务器"+words[1]+"下载"); 106 | 107 | filename=words[0];//切换成块文件名称 108 | host=words[1]; 109 | 110 | 111 | Socket socket = new Socket(InetAddress.getByName(host),20527); 112 | System.out.println("成功连接到服务器: "+host); 113 | 114 | //给服务器发送文件名 115 | DataOutputStream outputStream = new DataOutputStream (socket.getOutputStream()); 116 | outputStream.writeUTF(filename); 117 | 118 | System.out.println("请求文件: " + filename); 119 | 120 | // ExecutorService exec=Executors.newCachedThreadPool(); 121 | // exec.execute(new Thread(new ClientThread(socket,filename))); 122 | 123 | //接收服务器的回应 124 | InputStream inputStream = socket.getInputStream(); 125 | //开辟本地文件的输出流,以存放从客户端发来的文件 126 | BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/downloads/" + filename )); 127 | byte[] data = new byte[1024]; 128 | int len = 0; 129 | while ( (len = inputStream.read(data)) != -1 ) { 130 | bos.write(data, 0, len); 131 | } 132 | System.out.println("文件已成功接收!"); 133 | 134 | inputStream.close(); 135 | outputStream.close(); 136 | bos.close(); 137 | socket.close(); 138 | bw.write(filename+"\n"); 139 | bw.flush(); 140 | 141 | } 142 | 143 | 144 | }catch(Exception e){ 145 | e.printStackTrace(); 146 | bw.close(); 147 | return;//停止下载,防止块文件乱序下载 148 | } 149 | 150 | bw.close(); 151 | mergeFile(); 152 | } 153 | } -------------------------------------------------------------------------------- /hw2/q2/2052717-hw2-q2-src&run/Client/Main.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.util.Scanner; 3 | 4 | public class Main{ 5 | public static void main(String args[]) throws IOException{ 6 | Scanner sc = new Scanner(System.in); 7 | System.out.println("请输入指令:"); 8 | String cmd=sc.next().toString(); 9 | 10 | 11 | if(cmd.equals("put")){ 12 | String filename=sc.next().toString(); 13 | 14 | long startTime = System.currentTimeMillis(); 15 | UploadClient upload=new UploadClient(filename); 16 | upload.main(); 17 | long endTime=System.currentTimeMillis(); 18 | long usedTime=(endTime-startTime); 19 | System.out.println("本次上传所用时间:"+usedTime+"ms"); 20 | } 21 | else if(cmd.equals("get")){ 22 | String filename=sc.next().toString(); 23 | 24 | long startTime = System.currentTimeMillis(); 25 | DownloadClient download=new DownloadClient(filename); 26 | download.main(); 27 | long endTime=System.currentTimeMillis(); 28 | long usedTime=(endTime-startTime); 29 | System.out.println("本次下载所用时间:"+usedTime+"ms"); 30 | } 31 | else if(cmd.equals("check")){ 32 | Check check=new Check(); 33 | check.main(); 34 | } 35 | else if(cmd.equals("cput")){ 36 | String filename=sc.next().toString(); 37 | 38 | long startTime = System.currentTimeMillis(); 39 | CputClient cput=new CputClient(filename); 40 | cput.main(); 41 | long endTime=System.currentTimeMillis(); 42 | long usedTime=(endTime-startTime); 43 | System.out.println("本次续传所用时间:"+usedTime+"ms"); 44 | } 45 | else if(cmd.equals("cget")){ 46 | String filename=sc.next().toString(); 47 | 48 | long startTime = System.currentTimeMillis(); 49 | CgetClient cget=new CgetClient(filename); 50 | cget.main(); 51 | long endTime=System.currentTimeMillis(); 52 | long usedTime=(endTime-startTime); 53 | System.out.println("本次续载所用时间:"+usedTime+"ms"); 54 | } 55 | 56 | } 57 | 58 | 59 | } -------------------------------------------------------------------------------- /hw2/q2/2052717-hw2-q2-src&run/Client/UploadClient.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedInputStream; 2 | import java.io.BufferedWriter; 3 | import java.io.Console; 4 | import java.io.DataOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.OutputStream; 12 | import java.io.OutputStreamWriter; 13 | import java.io.RandomAccessFile; 14 | import java.net.Socket; 15 | import java.util.HashMap; 16 | import java.util.Iterator; 17 | import java.util.Random; 18 | 19 | public class UploadClient { 20 | 21 | static String filename="";//文件名 22 | static long chunkFileNum=0; 23 | static String chunkname=""; 24 | static String filewithoutPath=""; 25 | 26 | public UploadClient(String name){ 27 | filename="src/"+name; 28 | filewithoutPath=name; 29 | } 30 | 31 | public static HashMap table = new HashMap<>(); 32 | 33 | //测试文件分块 34 | public static void Chunk() throws IOException { 35 | //源文件 36 | 37 | File sourceFile = new File(filename); 38 | //块文件目录 39 | String chunkFileFolder = "src/chunks/"; 40 | 41 | //先定义块文件大小 42 | long chunkFileSize = 1 * 1024 * 1024; 43 | 44 | //块数 45 | chunkFileNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkFileSize); 46 | System.out.println(chunkFileNum); 47 | 48 | Random ran = new Random(); 49 | 50 | //创建读文件的对象 51 | RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r"); 52 | 53 | chunkname=sourceFile.getName(); 54 | // .replace(".", ""); 55 | 56 | System.out.println(filename); 57 | System.out.println(chunkname); 58 | //缓冲区 59 | byte[] b = new byte[1024]; 60 | 61 | for (int i = 0; i < chunkFileNum; i++) { 62 | //块文件 63 | File chunkFile = new File(chunkFileFolder +chunkname+ i); 64 | 65 | System.out.println(chunkFile); 66 | //创建向块文件的写对象 67 | RandomAccessFile raf_write = new RandomAccessFile(chunkFile, "rw"); 68 | 69 | //给该块分配服务器 70 | table.put(chunkFile.getName(),ran.nextInt(2)); 71 | 72 | int len = -1; 73 | 74 | while ((len = raf_read.read(b)) != -1) { 75 | 76 | raf_write.write(b, 0, len); 77 | //如果块文件的大小达到 1M开始写下一块儿 78 | if (chunkFile.length() >= chunkFileSize) { 79 | break; 80 | } 81 | } 82 | raf_write.close(); 83 | 84 | 85 | } 86 | raf_read.close(); 87 | } 88 | 89 | 90 | public static void uploadClient() throws IOException{ 91 | String host1="192.168.56.102"; 92 | String host2 = "192.168.56.104"; 93 | String host =""; 94 | int port = 20527; 95 | File progFile=new File("src/uploadProg/prog_"+filewithoutPath+".txt"); 96 | BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(progFile,true))); 97 | 98 | for (int i=0;i 2 | 3 | $PROJECT_DIR$/out/artifacts/dblp_q1_jar 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/dblp_q1.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/artifacts/dblp_q1_jar/dataServer.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/artifacts/dblp_q1_jar/dataServer.jar -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.app.server.DataServer 3 | 4 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/client/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/client/Main.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/client/RequestClient$RunnableSearch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/client/RequestClient$RunnableSearch.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/client/RequestClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/client/RequestClient.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/common/ServerInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/common/ServerInfo.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/datanode/DataNode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/datanode/DataNode.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/datanode/UploadClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/datanode/UploadClient.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/datanode/XmlPreprocess.py: -------------------------------------------------------------------------------- 1 | import re 2 | import json 3 | 4 | data={ 5 | "Paul Kocher":{ 6 | 2020: 0 7 | } 8 | } 9 | 10 | with open('E:\\underreality\\dblp_1_1_1.xml','r',encoding='utf-8') as f: 11 | # key=False 12 | author=[] 13 | for line in f.readlines(): 14 | if "key=" in line: 15 | authors=[] 16 | if "([\s\S]*?)',line,re.M|re.I) 18 | if searchObj: 19 | authors.append(searchObj.group(2)) 20 | if "" in line: 21 | searchObj=re.search(r'([\d]*?)',line,re.M|re.I) 22 | if searchObj: 23 | year=int(searchObj.group(1)) 24 | for author in authors: 25 | #data["author"] 26 | if data.__contains__(author): 27 | if data[author].__contains__(year): 28 | data[author][year]+=1 29 | else: 30 | data[author][year]=1 31 | else: 32 | data[author]={} 33 | data[author][year]=1 34 | 35 | # print(data) 36 | json_data = json.dumps(data,indent=2,sort_keys=True) 37 | # print(json_data) 38 | f2=open('new_json.json','w') 39 | f2.write(json_data) 40 | f2.close() 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/DataServer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/DataServer.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/Query$RunnableQuery.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/Query$RunnableQuery.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/Query.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/Query.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/QueryServer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/QueryServer.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/UploadServerThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/UploadServerThread.class -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/files/1-0.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | Paul Kocher 4 | Daniel Genkin 5 | Daniel Gruss 6 | Werner Haas 0004 7 | Mike Hamburg 8 | Yuyuan Putao 9 | Stefan Mangard 10 | Thomas Prescher 0002 11 | Michael Schwarz 0001 12 | Yuval Yarom 13 | Spectre Attacks: Exploiting Speculative Execution. 14 | meltdownattack.com 15 | 2018 16 | https://spectreattack.com/spectre.pdf 17 |
18 |
19 | Moritz Lipp 20 | Michael Schwarz 0001 21 | Daniel Gruss 22 | Thomas Prescher 0002 23 | Werner Haas 0004 24 | Stefan Mangard 25 | Paul Kocher 26 | Daniel Genkin 27 | Yuval Yarom 28 | Mike Hamburg 29 | Meltdown 30 | meltdownattack.com 31 | https://meltdownattack.com/meltdown.pdf 32 | 2018 33 |
34 | 35 | Computer Science Curricula 2013 36 | ACM Press and IEEE Computer Society Press 37 | Paul Kocher 38 | 2013 39 | https://doi.org/10.1145/2534860 40 | https://www.wikidata.org/entity/Q107021707 41 | 978-1-4503-2309-3 42 |
43 | Frank Manola 44 | An Evaluation of Object-Oriented DBMS Developments: 1994 Edition. 45 | GTE Laboratories Incorporated 46 | TR-0263-08-94-165 47 | August 48 | 1994 49 | db/journals/gtelab/index.html#TR-0263-08-94-165 50 |
51 | Michael L. Brodie 52 | Michael Stonebraker 53 | DARWIN: On the Incremental Migration of Legacy Information Systems 54 | GTE Laboratories Incorporated 55 | TR-0222-10-92-165 56 | March 57 | 1993 58 | db/journals/gtelab/index.html#TR-0222-10-92-165 59 | This report is also available as a Technical Memorandum of Electronics Research Laboratory, College of Engineering, University of California, Berkeley. 60 |
61 |
-------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/files/2-1.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | Paul Kocher 4 | Daniel Genkin 5 | Daniel Gruss 6 | Werner Haas 0004 7 | Mike Hamburg 8 | Yuyuan Putao 9 | Stefan Mangard 10 | Thomas Prescher 0002 11 | Michael Schwarz 0001 12 | Yuval Yarom 13 | Spectre Attacks: Exploiting Speculative Execution. 14 | meltdownattack.com 15 | 2018 16 | https://spectreattack.com/spectre.pdf 17 |
18 |
19 | Moritz Lipp 20 | Michael Schwarz 0001 21 | Daniel Gruss 22 | Thomas Prescher 0002 23 | Werner Haas 0004 24 | Stefan Mangard 25 | Paul Kocher 26 | Daniel Genkin 27 | Yuval Yarom 28 | Mike Hamburg 29 | Meltdown 30 | meltdownattack.com 31 | https://meltdownattack.com/meltdown.pdf 32 | 2018 33 |
34 | 35 | Computer Science Curricula 2013 36 | ACM Press and IEEE Computer Society Press 37 | Paul Kocher 38 | 2013 39 | https://doi.org/10.1145/2534860 40 | https://www.wikidata.org/entity/Q107021707 41 | 978-1-4503-2309-3 42 |
43 | Frank Manola 44 | An Evaluation of Object-Oriented DBMS Developments: 1994 Edition. 45 | GTE Laboratories Incorporated 46 | TR-0263-08-94-165 47 | August 48 | 1994 49 | db/journals/gtelab/index.html#TR-0263-08-94-165 50 |
51 | Michael L. Brodie 52 | Michael Stonebraker 53 | Paul Kocher 54 | DARWIN: On the Incremental Migration of Legacy Information Systems 55 | GTE Laboratories Incorporated 56 | TR-0222-10-92-165 57 | March 58 | 1993 59 | db/journals/gtelab/index.html#TR-0222-10-92-165 60 | This report is also available as a Technical Memorandum of Electronics Research Laboratory, College of Engineering, University of California, Berkeley. 61 | 62 | 63 | Michael L. Brodie 64 | Michael Stonebraker 65 | Paul Kocher 66 | DARWIN: On the Incremental Migration of Legacy Information Systems 67 | GTE Laboratories Incorporated 68 | TR-0222-10-92-165 69 | March 70 | 1993 71 | db/journals/gtelab/index.html#TR-0222-10-92-165 72 | This report is also available as a Technical Memorandum of Electronics Research Laboratory, College of Engineering, University of California, Berkeley. 73 | 74 |
-------------------------------------------------------------------------------- /期末项目/作业1-项目源码/out/production/dblp_q1/com/app/server/test.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | Paul Kocher 4 | Daniel Genkin 5 | Daniel Gruss 6 | Werner Haas 0004 7 | Mike Hamburg 8 | Yuyuan Putao 9 | Stefan Mangard 10 | Thomas Prescher 0002 11 | Michael Schwarz 0001 12 | Yuval Yarom 13 | Spectre Attacks: Exploiting Speculative Execution. 14 | meltdownattack.com 15 | 2018 16 | https://spectreattack.com/spectre.pdf 17 |
18 |
19 | Moritz Lipp 20 | Michael Schwarz 0001 21 | Daniel Gruss 22 | Thomas Prescher 0002 23 | Werner Haas 0004 24 | Stefan Mangard 25 | Paul Kocher 26 | Daniel Genkin 27 | Yuval Yarom 28 | Mike Hamburg 29 | Meltdown 30 | meltdownattack.com 31 | https://meltdownattack.com/meltdown.pdf 32 | 2018 33 |
34 | 35 | Computer Science Curricula 2013 36 | ACM Press and IEEE Computer Society Press 37 | Paul Kocher 38 | 2013 39 | https://doi.org/10.1145/2534860 40 | https://www.wikidata.org/entity/Q107021707 41 | 978-1-4503-2309-3 42 |
43 | Frank Manola 44 | An Evaluation of Object-Oriented DBMS Developments: 1994 Edition. 45 | GTE Laboratories Incorporated 46 | TR-0263-08-94-165 47 | August 48 | 1994 49 | db/journals/gtelab/index.html#TR-0263-08-94-165 50 |
51 | Michael L. Brodie 52 | Michael Stonebraker 53 | DARWIN: On the Incremental Migration of Legacy Information Systems 54 | GTE Laboratories Incorporated 55 | TR-0222-10-92-165 56 | March 57 | 1993 58 | db/journals/gtelab/index.html#TR-0222-10-92-165 59 | This report is also available as a Technical Memorandum of Electronics Research Laboratory, College of Engineering, University of California, Berkeley. 60 |
61 |
-------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.app.server.DataServer 3 | 4 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/client/Logger.java: -------------------------------------------------------------------------------- 1 | package com.app.client; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.OutputStreamWriter; 8 | 9 | public class Logger { 10 | File file; 11 | public Logger(){ 12 | file=new File("client.log"); 13 | try { 14 | file.createNewFile(); 15 | } catch (IOException e) { 16 | // TODO Auto-generated catch block 17 | System.out.println(file.getName()+"文件已存在!"); 18 | } 19 | 20 | } 21 | 22 | public void writeInfo(String text){ 23 | //将text写入到log最后一行 24 | try(BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true)))){ 25 | StringBuffer stringBuffer = new StringBuffer(); 26 | long timestamp=System.currentTimeMillis(); 27 | stringBuffer.append(String.valueOf(timestamp)+" "); 28 | stringBuffer.append(text); 29 | stringBuffer.append("\n"); 30 | bw.write(stringBuffer.toString()); 31 | }catch(Exception e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/client/Main.java: -------------------------------------------------------------------------------- 1 | package com.app.client; 2 | 3 | import java.io.IOException; 4 | import java.util.Objects; 5 | import java.util.Scanner; 6 | 7 | public class Main { 8 | public static void main(String args[]) throws IOException, InterruptedException { 9 | System.out.println("进入DBLP数据查询系统...(输入q退出)"); 10 | Scanner scan = new Scanner(System.in); 11 | String name = ""; 12 | int start = -1; 13 | int end = -1; 14 | 15 | while (true) { //暂时不实现轮询功能 16 | System.out.println(""); 17 | System.out.println("请输入要查询的作者姓名...)"); 18 | if (scan.hasNextLine()) { 19 | name = scan.nextLine(); 20 | if (name.equals("q")) 21 | return; 22 | } 23 | 24 | System.out.println("请输入要查询的论文范围的年份下限(包括输入的年份,若无最小年份限制则输入-1)..."); 25 | if (scan.hasNextLine()) 26 | try { 27 | String op = scan.nextLine(); 28 | if (op.equals("q")) 29 | return; 30 | start = Integer.parseInt(op); 31 | } catch (NumberFormatException e) { 32 | System.out.println("请输入合理的年份!"); 33 | // continue; 34 | } 35 | System.out.println("请输入要查询的论文范围的年份上限(包括输入的年份,若无最大年份限制则输入-1)..."); 36 | if (scan.hasNextLine()) 37 | try { 38 | String op = scan.nextLine(); 39 | if (op.equals("q")) 40 | return; 41 | end = Integer.parseInt(op); 42 | } catch (NumberFormatException e) { 43 | System.out.println("请输入合理的年份!"); 44 | // continue; 45 | } 46 | 47 | 48 | RequestClient requestClient = new RequestClient(name, start, end); 49 | int []ans=requestClient.search("hash"); 50 | int sum=0; 51 | for(int i=0;i<3;i++){//0 1 2 52 | // 53 | System.out.println(ans[i]); 54 | sum+=ans[i]; 55 | } 56 | System.out.println(name+"在"+start+"-"+end+"年发表论文在DBLP有记录的有"+sum+"篇"); 57 | 58 | 59 | } 60 | 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/client/RequestClient.java: -------------------------------------------------------------------------------- 1 | package com.app.client; 2 | 3 | import com.app.common.ServerInfo; 4 | 5 | import java.io.*; 6 | import java.net.Socket; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.concurrent.CountDownLatch; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class RequestClient { 14 | 15 | public static Logger logger=new Logger(); 16 | private int []chunk={0,0,0,0};//目前4块, 要求块序号从0开始 17 | 18 | private String requestName; 19 | private int startYear; 20 | private int endYear; 21 | static ServerInfo serverInfo = new ServerInfo(); 22 | 23 | // public static long exetime=0; 24 | 25 | 26 | public RequestClient(String name, int start, int end) { 27 | requestName = name; 28 | startYear = start; 29 | endYear = end; 30 | } 31 | 32 | public void printInfo() { 33 | System.out.println("姓名:" + requestName + " 年份:" + startYear + "-" + endYear); 34 | } 35 | 36 | // public void showResult(){ 37 | 38 | // } 39 | 40 | //向各个输出流里写入String 41 | private static void writeUTF(ArrayList outputStreams, String info) throws IOException { 42 | for (int i = 0; i < outputStreams.size(); i++) { 43 | (outputStreams.get(i)).writeUTF(info); 44 | } 45 | return; 46 | } 47 | 48 | //向各个输出流中写入int 49 | private static void writeInt(ArrayList outputStreams, int info) throws IOException { 50 | for (int i = 0; i < outputStreams.size(); i++) { 51 | (outputStreams.get(i)).writeInt(info); 52 | } 53 | return; 54 | } 55 | 56 | 57 | class RunnableSearch implements Runnable{ 58 | 59 | private Thread t; 60 | private String threadName; 61 | private String type; 62 | private String ip; 63 | private int port; 64 | private CountDownLatch threadsSignal; 65 | 66 | RunnableSearch(String name,String type,String ip,int port,CountDownLatch threadsSignal){ 67 | threadName=name; 68 | this.type=type; 69 | this.ip=ip; 70 | this.port=port; 71 | this.threadsSignal=threadsSignal; 72 | 73 | System.out.println("客户端创建线程"+name); 74 | System.out.println("尝试通过端口"+port+"连接服务器"+ip); 75 | } 76 | 77 | public void start(){ 78 | // System.out.println("线程开始"); 79 | if(t==null){ 80 | t=new Thread(this,threadName); 81 | t.start(); 82 | } 83 | } 84 | 85 | 86 | public void run(){ 87 | 88 | System.out.println("线程"+threadName+"开始运行"); 89 | ArrayList dataOutputStreams = new ArrayList<>(); 90 | ArrayList dataInputStreams = new ArrayList<>(); 91 | Socket socket; 92 | 93 | //与服务器建立连接 94 | 95 | try { 96 | socket = new Socket(ip, port); 97 | DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); 98 | DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); 99 | 100 | dataOutputStreams.add(dataOutputStream); 101 | dataInputStreams.add(dataInputStream); 102 | System.out.println("服务器" +ip + "连接成功!"); 103 | logger.writeInfo("服务器" +ip + "连接成功!"); 104 | } catch (IOException e) { 105 | System.out.println("服务器" + ip + "连接错误!"); 106 | logger.writeInfo("服务器" + ip + "连接错误!"); 107 | threadsSignal.countDown(); 108 | return; 109 | } 110 | try { 111 | 112 | writeUTF(dataOutputStreams,type); 113 | writeUTF(dataOutputStreams,requestName); 114 | writeInt(dataOutputStreams,startYear); 115 | writeInt(dataOutputStreams,endYear); 116 | 117 | // 获取服务端的返回信息 118 | //todo:确定返回信息的格式以及返回信息的处理 119 | for (int i = 0; i < dataInputStreams.size(); i++) { 120 | String result = (dataInputStreams.get(i)).readUTF(); 121 | System.out.println("服务器发回结果:"+result); 122 | logger.writeInfo("服务器发回结果:"+result); 123 | //1-2-3 块-副本号-查询结果 124 | 125 | int chunkIdx=0; 126 | int queryRes=0; 127 | //汇总多个服务端结果,得到作者论文总数 128 | for (String res: result.split(",")){ 129 | int t=2; 130 | while(t>=1){ 131 | Pattern p=Pattern.compile("([\\d]*?)-"); 132 | Matcher m=p.matcher(res); 133 | 134 | if(m.find()){ 135 | String st=m.group(1); 136 | if(t==2) chunkIdx=Integer.valueOf(st); 137 | else queryRes=Integer.valueOf(st); 138 | } 139 | chunk[chunkIdx]=queryRes; 140 | if(t==2) res=new StringBuffer(res).reverse().toString(); 141 | t--; 142 | } 143 | 144 | } 145 | } 146 | 147 | } catch (IOException e) { 148 | System.out.println("socket通信失败!"); 149 | threadsSignal.countDown(); 150 | return; 151 | } 152 | 153 | //输出结果 154 | 155 | 156 | //关闭socket 157 | try { 158 | socket.close(); 159 | System.out.println("线程"+threadName+"socket已关闭"); 160 | } catch (IOException e) { 161 | System.out.println("关闭socket失败!"); 162 | } 163 | 164 | threadsSignal.countDown(); 165 | 166 | 167 | 168 | // } 169 | } 170 | } 171 | 172 | 173 | /** 174 | * requestClient的主体功能函数,与服务端交互实现查询的具体操作 175 | * 176 | * @param type common:采取默认方式 hash:采取哈希表方式 177 | * @throws InterruptedException 178 | */ 179 | public int[] search(String type) throws InterruptedException { 180 | //与服务器建立连接 181 | CountDownLatch threadSignal=new CountDownLatch(serverInfo.serverNum); 182 | long commonStartTime = System.currentTimeMillis(); 183 | long commonUsedTime=0; 184 | System.out.println("与服务器建立连接..."); 185 | for (int i = 0; i < serverInfo.serverNum; i++) { 186 | RunnableSearch r=new RunnableSearch("t"+i, type, serverInfo.ipList[i], serverInfo.queryPort,threadSignal); 187 | r.start(); 188 | } 189 | 190 | 191 | threadSignal.await(); 192 | 193 | long commonEndTime = System.currentTimeMillis(); 194 | commonUsedTime += (commonEndTime - commonStartTime); 195 | 196 | 197 | System.out.println("使用"+type+"类型查询所用时间:" + commonUsedTime + "ms"); 198 | logger.writeInfo("使用"+type+"类型查询所用时间:" + commonUsedTime + "ms"); 199 | 200 | return chunk; 201 | 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/common/ServerInfo.java: -------------------------------------------------------------------------------- 1 | package com.app.common; 2 | 3 | public class ServerInfo { 4 | //存储关于服务器列表的信息 5 | //每个服务器有一个端口用于与queryClient通信,一个端口与dataNode通信 6 | public int serverNum = 4; 7 | // public final int[] queryPortList = new int[]{2717,4399}; 8 | public final int queryPort=2717; 9 | public final int dataPort = 8081; 10 | public final String[] ipList = new String[]{"1.15.100.12","47.100.170.76","101.34.3.28","47.97.182.183"}; 11 | public final String[] filePathList = new String[]{ 12 | "/home/ubuntu/files", "/root/usr/chen/files", "/home/ubuntu/files","/root/files"}; 13 | } 14 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/datanode/DataNode.java: -------------------------------------------------------------------------------- 1 | package com.app.datanode; 2 | 3 | import java.io.*; 4 | import java.nio.file.*; 5 | import java.util.ArrayList; 6 | 7 | import com.app.common.ServerInfo; 8 | 9 | /** 10 | * 实现存储负载均衡 11 | * 将dblp.xml文件随机分块并存储到每个StorageServer中 12 | */ 13 | public class DataNode { 14 | static String xmlPath = "E:\\underreality\\大三上\\分布式系统\\dblp.xml"; 15 | 16 | public static long getFileLineNum(String filePath) { 17 | try { 18 | return Files.lines(Paths.get(filePath)).count(); 19 | } catch (IOException e) { 20 | return -1; 21 | } 22 | } 23 | 24 | //判断一行是否是一段xml的开头 25 | private static boolean isStart(String line) { 26 | return line.contains("mdate") && line.contains("key"); 27 | } 28 | 29 | 30 | //将一个xml文件均衡分割成num份 31 | private static void splitXml(int num) { 32 | //创建io流 33 | long FileLine = getFileLineNum(xmlPath); 34 | FileInputStream fis = null; 35 | InputStreamReader isr = null; 36 | BufferedReader br = null; 37 | //创建分割文件的指标 38 | //每个小文件的大致大小 39 | long FileNodeLine = FileLine / num; 40 | //分割线 41 | ArrayList SplitLine = new ArrayList(); 42 | //起始文件行 43 | String FileNodeHeader = ""; 44 | for (int i = 1; i < num; i++) 45 | SplitLine.add(FileNodeLine * i); 46 | SplitLine.add(FileLine); 47 | try { 48 | File file = new File(xmlPath); 49 | String name = file.getName(); 50 | fis = new FileInputStream(file); 51 | isr = new InputStreamReader(fis); 52 | br = new BufferedReader(isr); 53 | String line = ""; 54 | //当前文件行序号 55 | long NodeLine = 1; 56 | //依次分割填充每个文件 57 | for (int Fileindex = 1; Fileindex <= num; Fileindex++) { 58 | int lastIndexOf = name.lastIndexOf("."); 59 | //源文件的去后缀名称 60 | String substring = name.substring(0, lastIndexOf); 61 | //源文件的后缀 62 | String substring2 = name.substring(lastIndexOf, name.length()); 63 | FileOutputStream fos = new FileOutputStream(substring + "_" + Fileindex + substring2); 64 | OutputStreamWriter osr = new OutputStreamWriter(fos); 65 | BufferedWriter bw = new BufferedWriter(osr); 66 | //将文件头部行写入子文件 67 | bw.write(FileNodeHeader); 68 | //读取基本分块 69 | while (NodeLine <= SplitLine.get(Fileindex - 1)) { 70 | line = br.readLine(); 71 | //读取行 72 | //处理尾标签放在下一行头部带来的切割文件的问题 73 | 74 | // if (line.length() >= 2 && line.charAt(0) == '<' && line.charAt(1) == '/' && line.indexOf('>') != line.lastIndexOf('>')) { 75 | // int index = line.indexOf('>'); 76 | // String line1 = line.substring(0, index + 1); 77 | // line1 = line1 + "\r\n"; 78 | // //不需要更新NodeLine! 79 | // String line2 = line.substring(index + 1); 80 | // line2 = line2 + "\r\n"; 81 | // line = line1 + line2; 82 | // } else { 83 | // line = line + "\r\n"; 84 | // } 85 | line = line + "\r\n"; 86 | bw.write(line); 87 | NodeLine++; 88 | } 89 | //一直遇到头部,停止读取,跳到下一个文件 90 | while (NodeLine <= FileLine) { 91 | line = br.readLine(); 92 | if (line.length() >= 2 && line.charAt(0) == '<' && line.charAt(1) == '/' && line.indexOf('>') != line.lastIndexOf('>')) { 93 | int index = line.indexOf('>'); 94 | String line1 = line.substring(0, index + 1); 95 | line1 = line1 + "\r\n"; 96 | bw.write(line1); 97 | String line2 = line.substring(index + 1); 98 | line2 = line2 + "\r\n"; 99 | line = line2; 100 | } else { 101 | line = line + "\r\n"; 102 | } 103 | if (isStart(line)) { 104 | FileNodeHeader = line; 105 | NodeLine++; 106 | break; 107 | } 108 | bw.write(line); 109 | NodeLine++; 110 | } 111 | //存在依赖关系,只需关闭bw流即可 112 | bw.close(); 113 | } 114 | 115 | } catch (FileNotFoundException e) { 116 | 117 | e.printStackTrace(); 118 | 119 | } catch (IOException e) { 120 | e.printStackTrace(); 121 | } finally { 122 | try { 123 | if (br != null) { 124 | br.close(); 125 | } 126 | } catch (IOException e) { 127 | e.printStackTrace(); 128 | } 129 | } 130 | } 131 | 132 | 133 | /** 134 | * DataNode脚本: 135 | * 1、通过spiltXml函数实现分割xml文件 136 | * 2、随机存储xml文件到服务器,实现负载均衡 137 | * 138 | * @throws IOException 139 | */ 140 | public static void main(String args[]) throws IOException { 141 | ServerInfo serverInfo = new ServerInfo(); 142 | //分隔xml文件 143 | splitXml(4); 144 | //根据算法分配文件,实现负载均衡 145 | // ArrayListUpLoadClients = new ArrayList(); 146 | // //建立client列表 147 | // for(int i=0;i< serverInfo.serverNum;i++){ 148 | // UploadClient client = new UploadClient(serverInfo.ipList[i],serverInfo.dataPort); 149 | // UpLoadClients.add(client); 150 | // } 151 | // //根据算法发送文件 152 | // for(int i=0;i< serverInfo.serverNum;i++){ 153 | // //分块文件名格式: dblp_i.xml 154 | // String filePath = "E:\\underreality\\大三上\\分布式系统\\dblp\\"+i+".xml"; 155 | 156 | // //服务器中块的命名格式: 块号_副本号.xml 157 | // //每个文件存2个副本是固定的 158 | // UpLoadClients.get(i% serverInfo.serverNum).send(filePath,i+"-0.xml"); 159 | // UpLoadClients.get((i+1)% serverInfo.serverNum).send(filePath,i+"-1.xml"); 160 | // UpLoadClients.get((i+2)% serverInfo.serverNum).send(filePath,i+"_2.xml"); 161 | // } 162 | } 163 | 164 | 165 | } 166 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/datanode/UploadClient.java: -------------------------------------------------------------------------------- 1 | package com.app.datanode; 2 | 3 | import java.io.DataOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | import java.net.Socket; 10 | 11 | 12 | 13 | public class UploadClient { 14 | 15 | static String ip; 16 | static int port; 17 | 18 | /** 19 | * uploadClient类:与一个对应的DataServer建立联系 20 | * 21 | * @param targetIp 目标服务器的ip 22 | * @param targetPort 目标服务器的端口 23 | */ 24 | public UploadClient(String targetIp, int targetPort) { 25 | ip = targetIp; 26 | port = targetPort; 27 | } 28 | 29 | /** 30 | * 传输一个文件到此client对应的server上 31 | * 32 | * @param filePath 要发送的文件地址 33 | * @param fileName 服务器端将此文件存储为什么名字 34 | * @throws IOException socket通信故障 35 | */ 36 | public void send(String filePath,String fileName) throws IOException { 37 | File file = new File(filePath); 38 | try { 39 | Socket socket = new Socket(ip, port); 40 | OutputStream outputStream = socket.getOutputStream(); //创建输出流对象 41 | DataOutputStream out = new DataOutputStream(outputStream); // 用于输出文件名 socket输出流 42 | FileInputStream inputStream = new FileInputStream(file); //读取要发送的本地文件 文件输入流 43 | out.writeUTF(fileName); //将文件名发送给服务器 44 | int len = -1; 45 | byte[] temp = new byte[1024]; 46 | while ((len = inputStream.read(temp)) != -1) { 47 | outputStream.write(temp, 0, len); 48 | } 49 | out.close(); //发送完毕后关闭输出流。 50 | outputStream.close(); 51 | System.out.println("成功发送"+fileName); 52 | } catch (Exception e) { 53 | System.out.println("UploadClient通信故障!"); 54 | e.printStackTrace(System.out); 55 | return;//不停止的话,就会造成乱序上传,导致日志顺序紊乱 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/datanode/XmlPreprocess.py: -------------------------------------------------------------------------------- 1 | import re 2 | import json 3 | import os 4 | 5 | data={} 6 | dirpath='E:\\underreality\\大三上\\分布式系统\\dblp\\' 7 | files=os.listdir(dirpath) 8 | 9 | # print(files) 10 | 11 | for file in files: 12 | 13 | with open(dirpath+file,'r',encoding='utf-8') as f: 14 | print(file+" start preprocessing") 15 | # key=False 16 | author=[] 17 | for line in f.readlines(): 18 | if "key=" in line: 19 | authors=[] 20 | if "([\s\S]*?)',line,re.M|re.I) 22 | if searchObj: 23 | authors.append(searchObj.group(2)) 24 | if "" in line: 25 | searchObj=re.search(r'([\d]*?)',line,re.M|re.I) 26 | if searchObj: 27 | year=int(searchObj.group(1)) 28 | for author in authors: 29 | #data["author"] 30 | if data.__contains__(author): 31 | if data[author].__contains__(year): 32 | data[author][year]+=1 33 | else: 34 | data[author][year]=1 35 | else: 36 | data[author]={} 37 | data[author][year]=1 38 | 39 | # print(data) 40 | json_data = json.dumps(data,indent=2,sort_keys=True) 41 | # print(json_data) 42 | f2=open(dirpath+file.split(".")[0]+'-0.json','w') 43 | f2.write(json_data) 44 | f2.close() 45 | 46 | f3=open(dirpath+file.split(".")[0]+'-1.json','w') 47 | f3.write(json_data) 48 | f3.close() 49 | 50 | print(file+" complete preprocess!") 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/server/DataServer.java: -------------------------------------------------------------------------------- 1 | package com.app.server; 2 | 3 | import java.io.IOException; 4 | import java.io.DataInputStream; 5 | import java.net.ServerSocket; 6 | import java.net.Socket; 7 | import java.util.concurrent.*; 8 | import com.app.common.ServerInfo; 9 | 10 | 11 | public class DataServer { 12 | public static void main(String[] args) { 13 | ServerInfo serverInfo = new ServerInfo(); 14 | try { 15 | ServerSocket serverSocket = new ServerSocket(serverInfo.dataPort); 16 | while(true){ 17 | System.out.println("server等待连接中..."); 18 | Socket accept = serverSocket.accept(); //在此处阻塞,只有当有文件发送过来时才执行后面的操作 19 | 20 | System.out.println("连接成功!"); 21 | 22 | DataInputStream in = new DataInputStream(accept.getInputStream()); 23 | String filename = in.readUTF(); 24 | //读取客户端发送过来的文件名 25 | System.out.println("读取文件名:"+filename); 26 | ExecutorService exec = Executors.newCachedThreadPool(); //创建一个执行器对象来为我们管理Thread对象 27 | 28 | exec.execute(new Thread(new UploadServerThread(accept,filename))); //启动任务 29 | } 30 | } catch (IOException e) { 31 | System.out.println("DataServer通信故障!"); 32 | return; 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /期末项目/作业1-项目源码/src/com/app/server/Query.java: -------------------------------------------------------------------------------- 1 | package com.app.server; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.nio.file.Paths; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Scanner; 12 | import java.util.concurrent.CountDownLatch; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | import com.app.common.ServerInfo; 17 | 18 | public class Query{ 19 | static ArrayList query_result=new ArrayList<>(); 20 | static String dirpath; 21 | 22 | static String name; 23 | static int start,end; 24 | 25 | Query(String name,int start,int end,String dirpath) throws Exception{ 26 | Query.name=name; 27 | Query.start=start; 28 | Query.end=end; 29 | Query.dirpath=dirpath; 30 | query_result.clear(); 31 | // search(); 32 | } 33 | 34 | public ArrayList getFiles(String path) throws Exception { 35 | //目标集合fileList 36 | ArrayList fileList = new ArrayList(); 37 | File file = new File(path); 38 | if(file.isDirectory()){ 39 | File []files = file.listFiles(); 40 | for(File fileIndex:files){ 41 | //如果这个文件是目录,则进行递归搜索 42 | if(fileIndex.isDirectory()){ 43 | getFiles(fileIndex.getPath()); 44 | }else{ 45 | int flag=fileIndex.getName().lastIndexOf('.'); 46 | String fileType=""; 47 | if(flag>0){ 48 | fileType=fileIndex.getName().substring(flag+1); 49 | } 50 | if(fileType.equals("json")){ 51 | //如果文件是json文件,则将文件句柄放入集合中 52 | fileList.add(fileIndex); 53 | } 54 | } 55 | } 56 | } 57 | return fileList; 58 | } 59 | 60 | 61 | class RunnableQuery implements Runnable { 62 | private Thread t; 63 | private String threadName; 64 | File file; 65 | private CountDownLatch threadsSignal; 66 | 67 | RunnableQuery(String name,File file,CountDownLatch threadsSignal){ 68 | threadName=name; 69 | this.file=file; 70 | this.threadsSignal=threadsSignal; 71 | System.out.println("服务器创建线程"+name); 72 | System.out.println("尝试访问文件"+file.getName()); 73 | } 74 | 75 | public void start(){ 76 | System.out.println("线程"+threadName+"开始"); 77 | if(t==null){ 78 | t=new Thread (this,threadName); 79 | t.start(); 80 | } 81 | } 82 | 83 | public void run(){ 84 | String filename=file.getName(); 85 | filename=filename.substring(0, filename.length()-5); 86 | int cnt=query(name,file.getPath(),start,end); 87 | 88 | query_result.add(filename+"-"+cnt); 89 | 90 | threadsSignal.countDown(); 91 | System.out.println("线程"+threadName+"关闭"); 92 | } 93 | 94 | } 95 | 96 | public List search() throws Exception{ 97 | ArrayList fileList = getFiles(dirpath); 98 | CountDownLatch threadSignal=new CountDownLatch(fileList.size()); 99 | for (int i=0;i res=q.search(); 40 | // return res; 41 | //返回结果 42 | 43 | String result=""; 44 | if(res.size()>=1) result+=res.get(0); 45 | for(int i=1;i 2 |
3 | Paul Kocher 4 | Daniel Genkin 5 | Daniel Gruss 6 | Werner Haas 0004 7 | Mike Hamburg 8 | Yuyuan Putao 9 | Stefan Mangard 10 | Thomas Prescher 0002 11 | Michael Schwarz 0001 12 | Yuval Yarom 13 | Spectre Attacks: Exploiting Speculative Execution. 14 | meltdownattack.com 15 | 2018 16 | https://spectreattack.com/spectre.pdf 17 |
18 |
19 | Moritz Lipp 20 | Michael Schwarz 0001 21 | Daniel Gruss 22 | Thomas Prescher 0002 23 | Werner Haas 0004 24 | Stefan Mangard 25 | Paul Kocher 26 | Daniel Genkin 27 | Yuval Yarom 28 | Mike Hamburg 29 | Meltdown 30 | meltdownattack.com 31 | https://meltdownattack.com/meltdown.pdf 32 | 2018 33 |
34 | 35 | Computer Science Curricula 2013 36 | ACM Press and IEEE Computer Society Press 37 | Paul Kocher 38 | 2013 39 | https://doi.org/10.1145/2534860 40 | https://www.wikidata.org/entity/Q107021707 41 | 978-1-4503-2309-3 42 |
43 | Frank Manola 44 | An Evaluation of Object-Oriented DBMS Developments: 1994 Edition. 45 | GTE Laboratories Incorporated 46 | TR-0263-08-94-165 47 | August 48 | 1994 49 | db/journals/gtelab/index.html#TR-0263-08-94-165 50 |
51 | Michael L. Brodie 52 | Michael Stonebraker 53 | DARWIN: On the Incremental Migration of Legacy Information Systems 54 | GTE Laboratories Incorporated 55 | TR-0222-10-92-165 56 | March 57 | 1993 58 | db/journals/gtelab/index.html#TR-0222-10-92-165 59 | This report is also available as a Technical Memorandum of Electronics Research Laboratory, College of Engineering, University of California, Berkeley. 60 |
61 | -------------------------------------------------------------------------------- /期末项目/作业2-报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-报告.pdf -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/dblp_q2.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/client/QueryClient$queryThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/client/QueryClient$queryThread.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/client/QueryClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/client/QueryClient.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/common/ServerInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/common/ServerInfo.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/Logger.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/Logger.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/Main.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/MemberList$MemberInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/MemberList$MemberInfo.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/MemberList.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/MemberList.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/ServerNode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/entity/ServerNode.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/1.15.100.12.log: -------------------------------------------------------------------------------- 1 | # 服务器1.15.100.12的日志 2 | # 仅作为test 3 | 2022-12-18-01:06 1.15.100.12 join 4 | 2022-12-18-01:06 update member list 5 | 2022-12-18-01:07 47.100.170.76 leave -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/CommonServer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/CommonServer.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$ReceiveBeating.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$ReceiveBeating.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$SendBeating.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$SendBeating.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$gossiping.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$gossiping.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$listentoIntroducer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon$listentoIntroducer.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Daemon.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Introducer$ReceiveChange.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Introducer$ReceiveChange.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Introducer$RunnableBroadCast.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Introducer$RunnableBroadCast.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Introducer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Introducer.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Query.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/期末项目/作业2-项目源码/out/production/dblp_q2/com/app/server/Query.class -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/client/QueryClient.java: -------------------------------------------------------------------------------- 1 | package com.app.client; 2 | 3 | 4 | import java.io.DataInputStream; 5 | import java.io.DataOutputStream; 6 | import java.io.IOException; 7 | import java.net.*; 8 | import java.util.ArrayList; 9 | import java.util.Objects; 10 | import java.util.Scanner; 11 | 12 | import com.app.common.ServerInfo; 13 | 14 | public class QueryClient { 15 | 16 | static ServerInfo serverInfo = new ServerInfo(); 17 | 18 | static ArrayList ipList = new ArrayList<>(); 19 | 20 | public static void main(String[] args) throws UnknownHostException { 21 | System.out.println("进入组成员日志查询系统...(输入q退出)"); 22 | Scanner scan = new Scanner(System.in); 23 | String info = ""; 24 | 25 | while (true) { 26 | System.out.println(""); 27 | System.out.println("请输入要查询的关键字..."); 28 | if (scan.hasNextLine()) { 29 | info = scan.nextLine(); 30 | if (info.equals("q")) 31 | return; 32 | query(info); 33 | } 34 | 35 | } 36 | } 37 | 38 | static class queryThread implements Runnable { 39 | static String ip; 40 | static String word; 41 | 42 | queryThread(String ip, String word) { 43 | 44 | queryThread.ip = ip; 45 | queryThread.word = word; 46 | } 47 | 48 | @Override 49 | public void run() { 50 | try { 51 | Socket socket = new Socket(ip, serverInfo.queryPort); 52 | DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); 53 | DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); 54 | dataOutputStream.writeUTF(word); 55 | String result = dataInputStream.readUTF(); 56 | System.out.println(result); 57 | } catch (IOException e) { 58 | System.out.println("[queryError]:无法与"+ip+"通信!"); 59 | } 60 | } 61 | 62 | } 63 | 64 | public static void query(String info) { 65 | //1.与introducer通信,获取现在存活的ip列表 66 | try { 67 | ipList = getIpList(); 68 | } catch (UnknownHostException e) { 69 | throw new RuntimeException(e); 70 | } 71 | //2.向各个ip发送请求 72 | System.out.println("[query]:开始查询..."); 73 | System.out.println("[query]:结果如下"); 74 | System.out.println("=========================="); 75 | for (String ip : ipList) { 76 | Thread t = new Thread(new queryThread(ip, info)); 77 | t.start(); 78 | } 79 | } 80 | 81 | //与introducer通信获取最新的列表 82 | public static ArrayList getIpList() throws UnknownHostException { 83 | InetAddress address; 84 | //introducer的ip地址 85 | address = InetAddress.getByName(serverInfo.introducerIp); 86 | //新加入节点的ip地址 87 | byte[] data = "client".getBytes();//发送ip 88 | // 2.创建数据报,包含发送的数据信息 89 | DatagramPacket packet = new DatagramPacket(data, data.length, address, serverInfo.introducerPort); 90 | try (// 3.创建DatagramSocket对象 91 | DatagramSocket socket = new DatagramSocket() 92 | ) { 93 | // 4.向服务器端发送数据报 94 | socket.send(packet); 95 | /* 96 | * 接收服务器端响应的数据 97 | */ 98 | // 1.创建数据报,用于接收服务器端响应的数据 99 | byte[] data2 = new byte[1024]; 100 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length); 101 | // 2.接收服务器响应的数据 102 | socket.setSoTimeout(10000); 103 | socket.receive(packet2); 104 | // 3.读取数据 105 | String reply = new String(data2, 0, packet2.getLength()); 106 | System.out.println("[query]:从introducer获取到最新的成员列表: \n" + reply); 107 | // 4.关闭资源 108 | socket.close(); 109 | 110 | if (reply.length() > 0) {//reply应为新的组成员列表的内容 111 | String[] newMemberList = reply.split("\n"); 112 | ipList.clear(); 113 | for (String newmember : newMemberList) { 114 | String newmember_ip = newmember.split(" ")[1]; 115 | ipList.add(newmember_ip); 116 | } 117 | } 118 | } catch (IOException e) { 119 | //出现异常 120 | System.out.println("[queryError]:无法与introducer通信!"); 121 | return ipList; 122 | } 123 | return ipList; 124 | } 125 | 126 | 127 | } -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/common/ServerInfo.java: -------------------------------------------------------------------------------- 1 | package com.app.common; 2 | 3 | import java.util.ArrayList; 4 | /** 5 | * 存储所有服务器结点(正常或者已离开的都算) 6 | * 存储一些需要共享的配置信息 7 | * 8 | */ 9 | public class ServerInfo { 10 | 11 | public static String []ip={"101.34.3.28","47.100.170.76","1.15.100.12"};// 12 | // public static String []receive_port={"2717","4399","3635"}; 13 | // public static String []send_port={"",""}; 14 | public final String introducerIp = "47.100.170.76"; 15 | 16 | //监听新节点加入与客户端查询 17 | public final int introducerPort = 2718; 18 | 19 | //监听节点的变化 20 | public final int introducerListPort = 2720; 21 | 22 | public final int broadcastPort=5500; 23 | 24 | public final int heartbeatingPort=8765; 25 | 26 | public final int gossipPort = 9010; 27 | 28 | public final int queryPort = 20527; 29 | 30 | //连续2次未回应,即认为断开连接 31 | public final int tolerate = 2; 32 | 33 | //丢包率, 默认为0 34 | public final double loss = 0; 35 | //全局状态列表 36 | //public static ArrayList state = new ArrayList<>(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/entity/Logger.java: -------------------------------------------------------------------------------- 1 | package com.app.entity; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStreamWriter; 9 | import java.util.Scanner; 10 | 11 | /** 12 | * 日志管理类 13 | * 14 | */ 15 | public class Logger { 16 | File file; 17 | String ip; 18 | public Logger(String ip){ 19 | this.ip=ip; 20 | System.out.println("[query]:打开的文件:"+ip+".log"); 21 | file=new File(ip+".log"); 22 | try { 23 | file.createNewFile(); 24 | } catch (IOException e) { 25 | // TODO Auto-generated catch block 26 | System.out.println("[query]:"+file.getName()+"文件已存在!"); 27 | } 28 | 29 | } 30 | 31 | public void writeInfo(String text){ 32 | //将text写入到log最后一行 33 | try(BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true)))){ 34 | StringBuffer stringBuffer = new StringBuffer(); 35 | long timestamp=System.currentTimeMillis(); 36 | stringBuffer.append(String.valueOf(timestamp)+" "); 37 | stringBuffer.append(text); 38 | stringBuffer.append("\n"); 39 | bw.write(stringBuffer.toString()); 40 | }catch(Exception e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | public String query(String keyword){ 46 | 47 | String result = ""; 48 | try (Scanner scanner = new Scanner(file)) { 49 | 50 | System.out.println("[query]:开始查询文件"); 51 | while (scanner.hasNextLine()) { 52 | String line = scanner.nextLine(); 53 | 54 | if (line.contains(keyword)) { 55 | result = result + line + "\r\n"; 56 | 57 | } 58 | } 59 | } catch (FileNotFoundException e) { 60 | System.out.println("[queryError]:找不到log."); 61 | } 62 | return result; 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/entity/MemberList.java: -------------------------------------------------------------------------------- 1 | package com.app.entity; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * 组成员列表实体类 7 | * 8 | */ 9 | public class MemberList { 10 | public static ArrayList members=new ArrayList<>(); 11 | 12 | public class MemberInfo{ 13 | String timestamp; 14 | public String ip; 15 | // public int port=9000; 16 | 17 | MemberInfo(String timestamp,String ip){ 18 | this.timestamp=timestamp; 19 | this.ip=ip; 20 | // this.port=port; 21 | } 22 | } 23 | 24 | //显示组成员列表 25 | public void show(){ 26 | for (MemberInfo member : members) { 27 | System.out.println(member.timestamp + " " + member.ip); 28 | } 29 | } 30 | 31 | //返回字符串形式的组成员列表 32 | public String members_toString(){ 33 | StringBuffer sb = new StringBuffer(); 34 | for (MemberInfo member:members){ 35 | sb.append(member.timestamp + " " + member.ip+"\n"); 36 | } 37 | return sb.toString(); 38 | } 39 | 40 | 41 | //添加组成员 42 | public void add(String timestamp,String ip){ 43 | MemberInfo newmember=new MemberInfo(timestamp, ip); 44 | // System.out.println(newmember); 45 | for(int i=0;i1){ 40 | System.out.println("指令输入格式错误!"); 41 | continue; 42 | } 43 | 44 | if (words[0].equals("check")) { 45 | if(daemon.inGroup) 46 | daemon.showGroup(); 47 | else{ 48 | System.out.println("daemon未成功加入!"); 49 | daemon.joinGroup(); 50 | } 51 | 52 | } else if (words[0].equals("exit")) { 53 | if(daemon.inGroup){ 54 | daemon.leave(); 55 | return; 56 | } 57 | else{ 58 | System.out.println("daemon已经不在组中!"); 59 | } 60 | return ; 61 | } else { 62 | System.out.println("指令输入格式错误!"); 63 | continue; 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/server/Daemon.java: -------------------------------------------------------------------------------- 1 | package com.app.server; 2 | 3 | import com.app.common.ServerInfo; 4 | import com.app.entity.Logger; 5 | import com.app.entity.MemberList; 6 | 7 | import java.io.IOException; 8 | import java.net.*; 9 | import java.time.LocalTime; 10 | 11 | /** 12 | * 维护组成员的线程 13 | * 1.探测相邻的节点是否存活 14 | * 2.主动离开 15 | * 3.显示组成员 16 | */ 17 | public class Daemon { 18 | public boolean inGroup = false; 19 | static String ip;//服务器自身的ip 20 | // static int port;//别人访问该服务器的port 21 | 22 | // static int gossipPort; 23 | 24 | //将三个子线程作为Daemon的属性,便于管理 25 | private Thread sendBeatingThread; 26 | 27 | public SendBeating sendBeating; 28 | 29 | private Thread receiveBeatingThread; 30 | 31 | private Thread gossipingThread; 32 | 33 | private Thread waitIntroduceThread; 34 | 35 | //每个daemon维护的全局状态列表 36 | MemberList memberList = new MemberList(); 37 | 38 | //获取introducer等常量配置 39 | ServerInfo serverInfo = new ServerInfo(); 40 | 41 | //日志维护 42 | Logger logger; 43 | 44 | //构造函数 45 | Daemon(String ip) { 46 | Daemon.ip = ip; 47 | logger=new Logger(ip); 48 | joinGroup(); 49 | } 50 | 51 | //人工处理是否丢包 52 | public boolean packageLost(double lossRate){ 53 | return !(Math.random() > lossRate); 54 | } 55 | 56 | public void send(DatagramSocket socket,DatagramPacket datagramPacket,double lossRate) throws IOException { 57 | if(packageLost(lossRate)) 58 | System.out.println("[info]:产生模拟丢包!"); 59 | else 60 | socket.send(datagramPacket); 61 | } 62 | 63 | void sendNewMemberMessage() throws IOException{ 64 | /* 65 | * 接收客户端发送的数据 66 | */ 67 | // 1.创建服务器端DatagramSocket,指定端口 68 | while(!waitIntroduceThread.isInterrupted()) { 69 | DatagramSocket socket = new DatagramSocket(serverInfo.broadcastPort); 70 | // 2.创建数据报,用于接收客户端发送的数据 71 | byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小 72 | DatagramPacket packet = new DatagramPacket(data, data.length); 73 | // 3.接收客户端发送的数据 74 | socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞 75 | // 4.读取数据 76 | String info = new String(data, 0, packet.getLength()); 77 | System.out.println("[new member]:新节点加入:" + info); 78 | 79 | String timestamp=info.split(" ")[0]; 80 | String newip=info.split(" ")[1]; 81 | memberList.add(timestamp, newip); 82 | 83 | /* 84 | * 向客户端响应数据 85 | */ 86 | // 1.定义客户端的地址、端口号、数据 87 | InetAddress address = packet.getAddress(); 88 | int port = packet.getPort(); 89 | byte[] data2 = (ip+"已收到新节点消息").getBytes(); 90 | // 2.创建数据报,包含响应的数据信息 91 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port); 92 | // 3.响应客户端 93 | socket.send(packet2); 94 | // 4.关闭资源 95 | socket.close(); 96 | } 97 | 98 | } 99 | 100 | 101 | class listentoIntroducer implements Runnable{ 102 | 103 | @Override 104 | public void run(){ 105 | try { 106 | sendNewMemberMessage(); 107 | } catch (IOException e) { 108 | // TODO Auto-generated catch block 109 | e.printStackTrace(); 110 | } 111 | 112 | } 113 | } 114 | 115 | public void joinGroup() { 116 | try { 117 | join(); 118 | inGroup = true; 119 | } catch (IOException e) { 120 | System.out.println("[error]:无法与introducer通信!"); 121 | } 122 | if (inGroup) { 123 | sendBeating = new SendBeating(); 124 | sendBeatingThread = new Thread(sendBeating);//检查下一个成员 125 | receiveBeatingThread = new Thread(new ReceiveBeating());//被上一个成员检查 126 | gossipingThread = new Thread(new gossiping()); 127 | waitIntroduceThread=new Thread(new listentoIntroducer()); 128 | 129 | sendBeatingThread.start(); 130 | receiveBeatingThread.start(); 131 | waitIntroduceThread.start(); 132 | gossipingThread.start(); 133 | } 134 | } 135 | 136 | //与introducer通信 137 | private void join() throws IOException { 138 | //向introducer发出加入请求 139 | request(ip); 140 | } 141 | 142 | public void request(String myip) throws UnknownHostException { 143 | 144 | /* 145 | * 向introducer发送join请求 146 | */ 147 | // 1.定义服务器的地址、端口号、数据 148 | InetAddress address; 149 | //introducer的ip地址 150 | address = InetAddress.getByName(serverInfo.introducerIp); 151 | //新加入节点的ip地址 152 | byte[] data = myip.getBytes();//发送ip 153 | // 2.创建数据报,包含发送的数据信息 154 | DatagramPacket packet = new DatagramPacket(data, data.length, address, serverInfo.introducerPort); 155 | 156 | while(true) { 157 | try (// 3.创建DatagramSocket对象 158 | DatagramSocket socket = new DatagramSocket() 159 | ) { 160 | // 4.向服务器端发送数据报 161 | //socket.send(packet); 162 | send(socket, packet, serverInfo.loss); 163 | /* 164 | * 接收服务器端响应的数据 165 | */ 166 | // 1.创建数据报,用于接收服务器端响应的数据 167 | byte[] data2 = new byte[1024]; 168 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length); 169 | // 2.接收服务器响应的数据 170 | socket.setSoTimeout(10000); 171 | socket.receive(packet2); 172 | // 3.读取数据 173 | String reply = new String(data2, 0, packet2.getLength()); 174 | System.out.println("[join]:从introducer获取到最新的成员列表: \n" + reply); 175 | // 4.关闭资源 176 | socket.close(); 177 | 178 | if (reply.length() > 0) {//reply应为新的组成员列表的内容 179 | System.out.println("[join]:成功加入!"); 180 | logger.writeInfo("join "+myip); 181 | String[] newMemberList = reply.split("\n"); 182 | 183 | for (String newmember : newMemberList) { 184 | String newmember_timeStamp = newmember.split(" ")[0]; 185 | String newmember_ip = newmember.split(" ")[1]; 186 | memberList.add(newmember_timeStamp, newmember_ip); 187 | } 188 | return; 189 | } 190 | System.out.println("[joinError]:"+myip + "无法加入"); 191 | } catch (IOException e) { 192 | //出现异常 193 | System.out.println("[joinError]:"+myip + "无法加入"); 194 | } 195 | } 196 | } 197 | 198 | //显示组成员 199 | public void showGroup() { 200 | memberList.show(); 201 | } 202 | 203 | //主动离开 204 | public void leave() { 205 | //发送gossip协议 206 | String info = "gossip"+" "+ip+" "+"leave"+" "+ip; 207 | logger.writeInfo(info); 208 | InetAddress address; 209 | DatagramPacket packet; 210 | InetAddress introducerAddress; 211 | DatagramPacket introducerPacket; 212 | try { 213 | //逆向传播消息 214 | address = InetAddress.getByName(memberList.findLastServer(ip)); 215 | introducerAddress = InetAddress.getByName(serverInfo.introducerIp); 216 | byte[] data = info.getBytes(); 217 | // 2.创建数据报,包含发送的数据信息 218 | packet = new DatagramPacket(data, data.length, address, serverInfo.gossipPort); 219 | introducerPacket = new DatagramPacket(data,data.length,introducerAddress,serverInfo.introducerListPort); 220 | DatagramSocket socket = new DatagramSocket(); 221 | socket.send(packet); 222 | socket.send(introducerPacket); 223 | } catch (UnknownHostException e) { 224 | return; 225 | } catch (IOException e) { 226 | throw new RuntimeException(e); 227 | } 228 | memberList.remove(ip); 229 | sendBeatingThread.interrupt(); 230 | receiveBeatingThread.interrupt(); 231 | gossipingThread.interrupt(); 232 | inGroup = false; 233 | System.out.println("[leave]:"+ip + "已主动离开"); 234 | 235 | } 236 | 237 | public void findLeave(String leaveIp){ 238 | //要删除的点就是原来自己探测的点 239 | assert leaveIp.equals(memberList.findNextServer(ip)); 240 | System.out.println("[failure]:检测到"+leaveIp+"故障"); 241 | //更新本地逻辑数组 242 | memberList.remove(leaveIp); 243 | //更新自己要检查的点 244 | sendBeating.ipToCheck = memberList.findNextServer(ip); 245 | // sendBeating.portToCheck = sendBeating.serverToCheck.port; 246 | sendBeating.errorNum=0; 247 | if (ip.equals(sendBeating.ipToCheck)) { 248 | System.out.println("[warning]:检测到组中现在只有一个成员!"); 249 | // return; 250 | } 251 | //发送gossip协议 252 | String info = "gossip"+" "+ip+" "+"failure"+" "+leaveIp; 253 | logger.writeInfo(info); 254 | 255 | InetAddress address; 256 | InetAddress introducerAddress; 257 | DatagramPacket packet; 258 | DatagramPacket introducerPacket; 259 | try { 260 | address = InetAddress.getByName(memberList.findLastServer(ip)); 261 | introducerAddress = InetAddress.getByName(serverInfo.introducerIp); 262 | byte[] data = info.getBytes(); 263 | // 2.创建数据报,包含发送的数据信息 264 | packet = new DatagramPacket(data, data.length, address, serverInfo.gossipPort); 265 | introducerPacket = new DatagramPacket(data,data.length,introducerAddress,serverInfo.introducerListPort); 266 | DatagramSocket socket = new DatagramSocket(); 267 | //socket.send(packet); 268 | send(socket,packet,serverInfo.loss); 269 | send(socket,introducerPacket,serverInfo.loss); 270 | } catch (UnknownHostException e) { 271 | return; 272 | } catch (IOException e) { 273 | throw new RuntimeException(e); 274 | } 275 | 276 | } 277 | 278 | 279 | //接受gossip包,并将其转发 280 | class gossiping implements Runnable{ 281 | @Override 282 | public void run() { 283 | try (DatagramSocket socket = new DatagramSocket(serverInfo.gossipPort)) { 284 | while(!gossipingThread.isInterrupted()) { 285 | // 2.创建数据报,用于接收客户端发送的数据 286 | byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小 287 | DatagramPacket packet = new DatagramPacket(data, data.length); 288 | // 3.接收客户端发送的数据 289 | // System.out.println("准备接收gossip..."); 290 | socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞 291 | // 4.读取数据 292 | String info = new String(data, 0, packet.getLength()); 293 | // System.out.println("收到gossip: "+ info); 294 | logger.writeInfo(info); 295 | String[] words = info.trim().split("\\s+"); 296 | 297 | if(words.length!=4 || !words[0].equals("gossip")) 298 | continue; 299 | 300 | //下一跳的地址 301 | String nextIp = "" ; 302 | 303 | //如果是探测的故障,则直接更新列表即可,其他结点不需改变探测拓扑 304 | if(words[2].equals("failure")) 305 | { 306 | //这里做了特判处理,不需要改变探测拓扑了(不过这样写可拓展性不高) 307 | System.out.println(words[3]); 308 | memberList.remove(words[3]); 309 | nextIp = memberList.findNextServer(ip); 310 | //打印日志() 311 | } 312 | 313 | if(words[2].equals("leave")){ 314 | //先找到原本的lastServer再改变memberList!否则会无法结束传播! 315 | System.out.println(words[3]+" leave"); 316 | nextIp = memberList.findLastServer(ip); 317 | //判断要不要改变探测拓扑 318 | if(sendBeating.ipToCheck.equals(words[3])){ 319 | memberList.remove(words[3]); 320 | sendBeating.ipToCheck=memberList.findNextServer(ip); 321 | sendBeating.errorNum=0; 322 | } 323 | else 324 | memberList.remove(words[3]); 325 | 326 | } 327 | 328 | assert nextIp.length()>0; 329 | // 转发gossip 330 | if(!nextIp.equals(words[1])) { 331 | InetAddress address = InetAddress.getByName(nextIp); 332 | // 2.创建数据报,包含响应的数据信息 333 | DatagramPacket packet2 = new DatagramPacket(data, data.length, address, serverInfo.gossipPort); 334 | // 3.响应客户端 335 | //socket.send(packet2); 336 | send(socket,packet2,serverInfo.loss); 337 | } 338 | } 339 | } catch (IOException e) { 340 | // TODO Auto-generated catch block 341 | System.out.println("[error]:gossip接收错误!"); 342 | e.printStackTrace(); 343 | } 344 | 345 | } 346 | } 347 | 348 | //heart-beating检测,daemon的内部类 349 | class SendBeating implements Runnable { 350 | 351 | String ipToCheck = memberList.findNextServer(ip); 352 | 353 | 354 | //发送检测信息的间隔时间 单位:毫秒 355 | int interval = 5000; 356 | 357 | //累积的错误次数,超过容忍度就认为结点故障了 358 | int errorNum = 0; 359 | 360 | 361 | @Override 362 | public void run() { 363 | /* 364 | * 每隔0.5s发送数据 365 | * todo:优化while循环的位置 366 | * 367 | */ 368 | //用udp访问,检测ipToCheck的状态 369 | 370 | 371 | while (!sendBeatingThread.isInterrupted()) { 372 | //check成员列表中排在自己之后的节点状态 373 | //休眠间隔 374 | try { 375 | Thread.sleep(interval); 376 | } catch (InterruptedException e) { 377 | // throw new RuntimeException(e); 378 | return; 379 | } 380 | 381 | ipToCheck = memberList.findNextServer(ip); 382 | 383 | 384 | //System.out.println("向"+ipToCheck+"发送heartbeating."); 385 | if(errorNum>=serverInfo.tolerate){ 386 | //重置errorNum 387 | errorNum=0; 388 | findLeave(ipToCheck); 389 | } 390 | //System.out.println(ip + "试图与" + ipToCheck + "建立udp通信"); 391 | // 1.定义服务器的地址、端口号、数据 392 | InetAddress address; 393 | DatagramPacket packet; //= new DatagramPacket(null, portToCheck); 394 | try { 395 | address = InetAddress.getByName(ipToCheck); 396 | byte[] data = (ipToCheck+"你还在吗?").getBytes(); 397 | // 2.创建数据报,包含发送的数据信息 398 | packet = new DatagramPacket(data, data.length, address, serverInfo.heartbeatingPort); 399 | 400 | } catch (UnknownHostException e) { 401 | System.out.println("[error]:unKnownHost"); 402 | System.out.println(e); 403 | errorNum++; 404 | continue; 405 | } 406 | 407 | try (// 3.创建DatagramSocket对象 408 | //这里是不需要加端口的(?) 409 | DatagramSocket socket = new DatagramSocket()) { 410 | // 4.向服务器端发送数据报 411 | //socket.send(packet); 412 | // System.out.print(LocalTime.now()); 413 | // System.out.println("向"+ipToCheck+"发送心跳"); 414 | send(socket,packet,serverInfo.loss); 415 | /* 416 | * 接收服务器端响应的数据 417 | * 创建计时器 418 | */ 419 | // 1.创建数据报,用于接收服务器端响应的数据 420 | byte[] data2 = new byte[1024]; 421 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length); 422 | // 2.接收服务器响应的数据 423 | //若超时未收到则报错 424 | socket.setSoTimeout(5000); 425 | socket.receive(packet2); 426 | // 3.读取数据 427 | String reply = new String(data2, 0, packet2.getLength()); 428 | // System.out.println(ipToCheck+"回复: " + reply); 429 | // 4.关闭资源 430 | // System.out.print(LocalTime.now()); 431 | // System.out.println("收到"+ipToCheck+"的回复 "); 432 | socket.close(); 433 | 434 | if (reply.equals("还在")) { 435 | // System.out.println(ipToCheck + "测试正常"); 436 | errorNum = 0; 437 | } 438 | 439 | } catch (IOException e) { 440 | System.out.println("[error]:IOException"); 441 | System.out.println(e); 442 | errorNum++; 443 | } 444 | 445 | } 446 | } 447 | } 448 | 449 | //与sendBeating相对的,接受来自其他结点的beating 450 | class ReceiveBeating implements Runnable { 451 | //check成员列表中排在自己之后的节点状态 452 | 453 | @Override 454 | public void run() { 455 | //用udp访问,检测ipToCheck的状态 456 | 457 | try (/* 458 | * 接收其他server发送的数据 459 | */ 460 | // 1.创建服务器端DatagramSocket,指定端口 461 | DatagramSocket socket = new DatagramSocket(serverInfo.heartbeatingPort)) { 462 | 463 | while(!receiveBeatingThread.isInterrupted()) { 464 | // 2.创建数据报,用于接收客户端发送的数据 465 | byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小 466 | DatagramPacket packet = new DatagramPacket(data, data.length); 467 | // 3.接收客户端发送的数据 468 | // System.out.println(ip + "等待其他成员发送heartbeating"); 469 | socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞 470 | // 4.读取数据 471 | String info = new String(data, 0, packet.getLength()); 472 | // System.out.println("有人发来消息:" + info); 473 | 474 | /* 475 | * 向客户端响应数据 476 | */ 477 | // 1.定义客户端的地址、端口号、数据 478 | InetAddress address = packet.getAddress(); 479 | int port = packet.getPort(); 480 | byte[] data2 = "还在".getBytes(); 481 | // 2.创建数据报,包含响应的数据信息 482 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port); 483 | // 3.响应客户端 484 | //socket.send(packet2); 485 | // System.out.print(LocalTime.now()); 486 | // System.out.println("向"+address+"发送回复 "); 487 | send(socket,packet2,serverInfo.loss); 488 | // System.out.println("回复: 还在"); 489 | // 4.关闭资源 490 | // socket在try的()中声明,退出try后会自动close。 491 | // socket.close(); 492 | } 493 | } catch (IOException e) { 494 | // TODO Auto-generated catch block 495 | System.out.println("[error]:ReceiveBeating接收错误!"); 496 | e.printStackTrace(); 497 | } 498 | 499 | } 500 | 501 | } 502 | 503 | 504 | } 505 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/server/Introducer.java: -------------------------------------------------------------------------------- 1 | package com.app.server; 2 | 3 | import java.io.IOException; 4 | import java.net.DatagramPacket; 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | import java.net.UnknownHostException; 8 | 9 | import com.app.common.ServerInfo; 10 | import com.app.entity.MemberList; 11 | import com.app.entity.MemberList.MemberInfo; 12 | 13 | public class Introducer { 14 | public static String ip="47.100.170.76"; 15 | static ServerInfo serverInfo=new ServerInfo(); 16 | 17 | //introducer节点也需要维护一个全局的表,且保证其是最新的,这样其他节点加进来的时候才不会出问题 18 | static MemberList memberList=new MemberList(); 19 | 20 | 21 | public static void addMember(String ipToAdd){ 22 | long timestamp=System.currentTimeMillis(); 23 | //始终等待新节点来找introducer 24 | //成功加入 25 | memberList.add(String.valueOf(timestamp), ipToAdd); 26 | spreadNewMember(String.valueOf(timestamp), ipToAdd); 27 | System.out.println("[introducer]:"+ipToAdd+"加入组!"); 28 | 29 | } 30 | 31 | static class RunnableBroadCast implements Runnable { 32 | String timeStamp; 33 | static String ip; 34 | String destip; 35 | Thread t; 36 | 37 | RunnableBroadCast(String timeStamp,String ip,String destip){ 38 | this.destip=destip; 39 | this.ip=ip; 40 | this.timeStamp=timeStamp; 41 | } 42 | public void start(){ 43 | if(t==null){ 44 | t=new Thread(this); 45 | t.start(); 46 | } 47 | } 48 | 49 | public void sendMessage() throws UnknownHostException { 50 | /* 51 | * 向members发送新成员join消息 52 | */ 53 | // 1.定义服务器的地址、端口号、数据 54 | InetAddress address = InetAddress.getByName(destip); 55 | //新加入节点的ip地址 56 | byte[] data = (timeStamp+" "+ip).getBytes();//发送ip 57 | // 2.创建数据报,包含发送的数据信息 58 | DatagramPacket packet = new DatagramPacket(data, data.length, address, serverInfo.broadcastPort); 59 | 60 | 61 | 62 | try (// 3.创建DatagramSocket对象 63 | DatagramSocket socket = new DatagramSocket()) { 64 | // 4.向服务器端发送数据报 65 | socket.send(packet); 66 | 67 | System.out.println("[introducer]:成功向" + destip + "发送新成员信息!"); 68 | 69 | /* 70 | * 接收服务器端响应的数据 71 | */ 72 | // 1.创建数据报,用于接收服务器端响应的数据 73 | byte[] data2 = new byte[1024]; 74 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length); 75 | // 2.接收服务器响应的数据 76 | socket.receive(packet2); 77 | // 3.读取数据 78 | String reply = new String(data2, 0, packet2.getLength()); 79 | 80 | System.out.println("[introducer]:从"+destip+"获取到reply: " + reply); 81 | 82 | // 4.关闭资源 83 | socket.close(); 84 | } catch (IOException e) { 85 | //出现异常 86 | System.out.println( "[introducerError]:无法向"+destip+"发送新成员加入消息!"); 87 | return; 88 | } 89 | } 90 | 91 | @Override 92 | public void run() { 93 | try { 94 | sendMessage(); 95 | } catch (UnknownHostException e) { 96 | // TODO Auto-generated catch block 97 | e.printStackTrace(); 98 | } 99 | } 100 | 101 | } 102 | 103 | static class ReceiveChange implements Runnable{ 104 | @Override 105 | public void run() { 106 | while (true) { 107 | try (DatagramSocket socket = new DatagramSocket(serverInfo.introducerListPort)) { 108 | // 2.创建数据报,用于接收客户端发送的数据 109 | byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小 110 | DatagramPacket packet = new DatagramPacket(data, data.length); 111 | // 3.接收客户端发送的数据 112 | socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞 113 | // 4.读取数据 114 | String info = new String(data, 0, packet.getLength()); 115 | // 5.解析数据 116 | String[] words = info.trim().split("\\s+"); 117 | 118 | if (words.length != 4 || !words[0].equals("gossip")) 119 | { 120 | System.out.println("[introducerError]:消息格式无效!"); 121 | continue; 122 | } 123 | 124 | if (words[2].equals("failure") || words[2].equals("leave")) { 125 | memberList.remove(words[3]); 126 | } 127 | } catch (IOException e) { 128 | System.out.println("[introducerError]:监听列表变化出现故障!"); 129 | e.printStackTrace(); 130 | } 131 | } 132 | } 133 | 134 | } 135 | 136 | private static void spreadNewMember(String timeStamp,String ip){ 137 | for (MemberInfo member:memberList.members){ 138 | RunnableBroadCast r=new RunnableBroadCast(timeStamp, ip, member.ip); 139 | r.start(); 140 | } 141 | 142 | } 143 | 144 | 145 | public static void main(String []args){ 146 | Thread listenListThread = new Thread(new ReceiveChange()); 147 | listenListThread.start(); 148 | while(true){ 149 | //introducer执行该程序 150 | try (/* 151 | * 接收其他server发送的数据 152 | */ 153 | // 1.创建服务器端DatagramSocket,指定端口 154 | DatagramSocket socket = new DatagramSocket(serverInfo.introducerPort)) { 155 | // 2.创建数据报,用于接收客户端发送的数据 156 | byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小 157 | DatagramPacket packet = new DatagramPacket(data, data.length); 158 | // 3.接收客户端发送的数据 159 | System.out.println("[introducer]: introducer("+ip+")已经启动,等待对方发送数据"); 160 | socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞 161 | // 4.读取数据 162 | String info = new String(data, 0, packet.getLength()); 163 | System.out.println("[introducer]:对方发来消息:" + info); 164 | 165 | /* 166 | * 向客户端响应数据 167 | */ 168 | // 1.定义客户端的地址、端口号、数据 169 | InetAddress address = packet.getAddress(); 170 | int port = packet.getPort(); 171 | //将新加入的节点更新至本地列表(关于端口的管理待定,端口可能是不需要维护在全局表中的) 172 | if(!info.equals("client")) 173 | addMember(info); 174 | 175 | byte[] data2 = memberList.members_toString().getBytes(); 176 | // 2.创建数据报,包含响应的数据信息 177 | DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port); 178 | // 3.响应客户端 179 | // 4.向全局更新memberlist 180 | socket.send(packet2); 181 | 182 | // 5.关闭资源 183 | socket.close(); 184 | 185 | } catch (IOException e) { 186 | // TODO Auto-generated catch block 187 | System.out.println("[error]:接收错误!"); 188 | e.printStackTrace(); 189 | } 190 | } 191 | } 192 | 193 | } 194 | 195 | -------------------------------------------------------------------------------- /期末项目/作业2-项目源码/src/com/app/server/Query.java: -------------------------------------------------------------------------------- 1 | package com.app.server; 2 | 3 | import com.app.common.ServerInfo; 4 | import com.app.entity.Logger; 5 | 6 | import java.io.DataInputStream; 7 | import java.io.DataOutputStream; 8 | import java.io.IOException; 9 | import java.net.InetAddress; 10 | import java.net.ServerSocket; 11 | import java.net.Socket; 12 | 13 | /** 14 | * 多线程的方式启动Query服务 15 | * 暂采用tcp方式通信 16 | * 单socket连接还是反复socket连接(线程里再开子线程)暂未定 17 | */ 18 | public class Query implements Runnable { 19 | 20 | ServerInfo serverInfo = new ServerInfo(); 21 | 22 | public void run() { 23 | try { 24 | System.out.println("[query]:启动query服务!"); 25 | ServerSocket serverSocket = new ServerSocket(serverInfo.queryPort); 26 | Logger logger = new Logger("47.100.170.76"); 27 | //1.建立连接等待客户端socket 28 | while (true) { 29 | Socket socket = serverSocket.accept(); 30 | DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); 31 | DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); 32 | String info = dataInputStream.readUTF(); 33 | String result = logger.query(info); 34 | dataOutputStream.writeUTF(result); 35 | } 36 | } catch (IOException e) { 37 | System.out.println("[error]:query服务端启动失败!"); 38 | } 39 | 40 | } 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /编程作业1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/编程作业1.pdf -------------------------------------------------------------------------------- /编程作业2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mossrain/Distributed-System/e604006919c20cf602508bcb76090a03f2d058df/编程作业2.pdf --------------------------------------------------------------------------------