赞
踩
[1]实验目的:理解Socket通信原理,掌握使用Socket和ServerSocket类进行TCP Socket通信的程序设计方法。
[2]实验内容:
1、使用ServerSocket类和Socket类实现按如下协议通信的服务器端和客户端程序。
服务器程序的处理规则如下:
客户端程序的处理规则如下:
服务器端:
- package experiment6.exp6_1;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.Objects;
-
- public class Exp6_1_Server {
- public static void main(String[] args) throws IOException {
- ServerSocket socket = new ServerSocket(6001);
- Socket server = socket.accept();
- String password;
- int count = 0;
- PrintWriter out = new PrintWriter(server.getOutputStream(), true);//返回TCP连接提供的字节输出流,将其格式化
- BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));//字节输入流转换为字符输入流,
- //BufferedReader 提供以缓冲方式读取一行字符串的方法
- out.println("Verifying Server!");
- while (true) {
- password = in.readLine(); //读取客户端数据
- System.out.println("Client:" + password);
- if (Objects.equals(password, "123456")) {
- out.println("Registration Successful!");
- System.out.println("Server:Registration Successful!");
- System.exit(0);
- } else {
- count++;
- if (count == 3) {
- out.println("Illegal User!");
- System.out.println("Server: Illegal User!");
- break;
- } else {
- out.println(" PassWord Wrong!");
- System.out.println("Server: PassWord Wrong!");
- }
- }
- }
- out.close();
- in.close();
- server.close();
- socket.close();
- }
- }

客户端
- package experiment6.exp6_1;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.Socket;
- import java.util.Scanner;
-
- public class Exp6_1_Client {
- public static void main(String[] args) throws IOException {
- Socket ser=new Socket("10.200.229.170",6001);
- Scanner scanner =new Scanner(System.in);
- String str,sc;
- PrintWriter out=new PrintWriter(ser.getOutputStream(),true);
- BufferedReader in=new BufferedReader(new InputStreamReader(ser.getInputStream()));
- while(true)
- {
- str=in.readLine();
- System.out.println("Server:"+str);
- if(str.equals("Illegal User!")||str.equals("Registration Successful!"))
- {
- break;
- }
- System.out.print("Client:");
- sc= scanner.next();
- out.println(sc);
- }
- out.close();
- in.close();
- ser.close();
- }
-
- }

登录失败情况:
Server:
Client:
登录成功情况:
Server:
Client:
2、实现聊天室功能。
1)完成服务器端和一个客户端之间的聊天功能。
2)扩展部分,采用多线程技术实现一个服务器端和多个客户端之间的聊天功能。
服务器端
- package experiment6.exp6_2;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Objects;
- import java.util.Scanner;
-
- public class server implements Runnable {// 服务端
- static List<Socket> socketList= new ArrayList<>();
- // 读取 In
- static Socket socket = null;
- static ServerSocket serverSocket = null;
- public server() {// 构造方法
- try {
- serverSocket = new ServerSocket(9999);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- int offline =0;
- public static void main(String[] args) {
- System.out.println("Server");
- server t = new server();
- System.out.println("Port 9999 remains to be connected......");
- int count = 0;
- while (true) {
- try {
- socket = serverSocket.accept();
- count++;
- System.out.println(count + " client(s) connected successfully!");
- socketList.add(socket);
- } catch (IOException e) {
- e.printStackTrace();
- }
- Print p = new Print(socket);
- Thread read = new Thread(t);
- Thread print = new Thread(p);
- read.start();
- print.start();
- }
- }
- @Override
- public void run() {
- // 重写run方法
- try {
- BufferedReader in = new BufferedReader(new InputStreamReader(socket
- .getInputStream()));
-
- while (true) {
- //接收消息
- String jieshou = in.readLine();
- if(jieshou == null){
- System.out.println("One client got offline");
- offline++;
- if(offline ==socketList.size()){
- System.out.println("All clients offline. Server offline now!");
- serverSocket.close();
- socket.close();
- System.exit(0);
- }
- break;}
- else
- System.out.println(jieshou);
-
- //向每一个客户发送接受的消息
- for (int i = 0; i < socketList.size(); i++) {
- Socket socket = socketList.get(i);
- PrintWriter out = new PrintWriter(socket.getOutputStream());
- out.println(jieshou);
- out.flush();
- }
- }
- } catch (Exception e) {
-
- }
- }
- }
-
-
- class Print implements Runnable {
- static List<Socket> socketList= new ArrayList<>();
- Scanner input = new Scanner(System.in);
- public Print(Socket s) {// 构造方法
- try {
- socketList.add(s);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- public void run() {
- try {
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
- while (true) {
- String msg = bufferedReader.readLine();
- if(Objects.equals(msg, "/quit")) System.exit(0);
- for (int i = 0; i < socketList.size(); i++) {
- //对每一个客户端发送消息
- Socket socket=socketList.get(i);
- PrintWriter out = new PrintWriter(socket.getOutputStream());
- out.println("Server: "+msg);
- out.flush();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }

客户端
- package experiment6.exp6_2;
-
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.Socket;
- import java.util.Objects;
- import java.util.Scanner;
-
- public class client implements Runnable {// 客户端
- static Socket socket = null;
- Scanner input = new Scanner(System.in);
- String name;
- client(String name){this.name=name;}
- public void main1() {
- System.out.println("Client "+name);
- try {
- socket = new Socket("localhost", 9999);
- System.out.println("Connected!");
- } catch (Exception e) {
- e.printStackTrace();
- }
- client t = new client(name);
- Read r = new Read(socket);
- Thread print = new Thread(t);
- Thread read = new Thread(r);
- print.start();
- read.start();
- }
- @Override
- public void run() {
- try {
- PrintWriter out = new PrintWriter(socket.getOutputStream());
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
- while (true) {
- //向客户端发送消息
- String msg = bufferedReader.readLine();
- if(Objects.equals(msg, "/quit")){
- socket.close();
- System.exit(0);
- }
-
- out.println(name+": "+msg);
- out.flush();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
-
- class Read implements Runnable {
- static Socket socket = null;
- public Read(Socket socket) {
- this.socket = socket;
- }
- @Override
- public void run() {
- try {
- BufferedReader in = new BufferedReader(new InputStreamReader(socket
- .getInputStream()));
- while (true) {
- //接受服务器的消息
- System.out.println(in.readLine());
- }
- } catch (Exception e) {
- System.out.println("Server offline! Connection Dismissed!");
- System.exit(0);
- }
- }
- }
-
- //client1
- package experiment6.exp6_2;
-
- import java.util.Scanner;
-
- public class client1 {
- public static void main(String[] args){
- System.out.println("请输入昵称:");
- Scanner scanner = new Scanner(System.in);
- client client_1 = new client(scanner.next());
- client_1.main1();
- }
- }
- //client2
- package experiment6.exp6_2;
-
- public class client2 {
- public static void main(String[] args){
- client client_2 = new client("fang");
- client_2.main1();
- }
- }

Server:
Client1:
Client2:
[3]实验分析
第一题比较简单,只有单个客户端和单个服务器端的简单通信,使用PrintWriter返回TCP连接提供的字节输出流,将其格式化,用BufferReader将字节输入流转化为字符输入流,同时提供以缓冲方式读取一行字符串的方法。
对于第二题,为了实现一个服务器端和多个客户端之间的通信,将读和写的功能分别置于两个线程当中,服务器端用一个socket列表来存放与所有客户端建立连接的socket,每发生一个连接,启动新的读写线程来进行通信。客户端和服务器端用BufferReader来进行整行字符串的读取。
在服务器端接收到某个客户端的消息后,还会将其进行转发,发送至每一个客户端,是的所有客户端之间能看见互相发送的消息。同时,为客户端和服务器端设立退出关键字“/quit”,输入“/quit”之后,客户端会关闭socket,结束程序,客户端下线;服务器端则会关闭所有socket,使得所有客户端也被迫退出通信。如果所有客户端均退出,服务器端自动关闭。
客户端也具备自己决定昵称的功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。