Java程序设计实验六 Socket网络程序设计

[1]实验目的:理解Socket通信原理,掌握使用Socket和ServerSocket类进行TCP Socket通信的程序设计方法。

[2]实验内容

1、使用ServerSocket类和Socket类实现按如下协议通信的服务器端和客户端程序。

服务器程序的处理规则如下:

  1. 向客户端程序发送Verifying Server!。
  2. 若读口令次数超过3次,则发送Illegal User!给客户端,程序退出。否则向下执行步骤3)。
  3. 读取客户端程序提供的口令。
  4. 若口令不正确,则发送PassWord Wrong!给客户端,并转步骤2),否则向下执行步骤5)。
  5. 发送Registration Successful!给客户端程序。

客户端程序的处理规则如下:

  1. 读取服务器反馈信息。
  2. 若反馈信息不是Verifying Server!,则提示Server Wrong!,程序退出。否则向下执行步骤3)
  3. 提示输入PassWord并将输入的口令发送给服务器。
  4. 读取服务器反馈信息。
  5. 若反馈信息是Illegal User!,则提示Illegal User!,程序退出。否则向下执行步骤6)
  6. 若反馈信息是PassWord Wrong!,则提示PassWord Wrong!,并转步骤3),否则向下执行步骤。
  7. 输出Registration Successful!。

 服务器端:

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,使得所有客户端也被迫退出通信。如果所有客户端均退出,服务器端自动关闭。

客户端也具备自己决定昵称的功能。

  • 8
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ace2NoU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值