TCP通信编程(Java)

一、实验目的和要求
1.掌握TCP/IP体系结构中端口、套接字、TCP协议概念。理解什端口的范围划分、套接字的组成等概念,掌握netstat等网络命令的使用;
2.掌握ServerSocket和Socket的使用,包括TCP连接的建立、服务器接收客户端连接请求、创建输入/输出流的方法以及关闭套接字等,注意可能会出现的异常操作;
3.理解进程和线程的概念,掌握Java多线程技术实现的主要方法,掌握多线程服务器程序的开发。
二、实验内容
1. 仔细阅读下述代码,分析功能功能,完善程序,并运行调试。
(1)客户端连接服务器端

import    java.io.*                     //引用输入与输出类库
import    java.net.*                    //引用网络类库
public class exp_1_1{
    public static void main(String [] args){
        String hostName = "www.xupt.edu.cn";
        int port = 80;
        Socket cs = null;
        try{
            cs = new   Socket   (hostName, port);
            System.out.println("连接"+hostName+"的端口"+port+"成功");
            System.out.println("对方主机" + cs.getInetAddress() + ":对方端口" + cs.getPort());
            System.out.println("本地主机" + cs.getLocalAddress() + ":本地端口" + cs.getLocalPort());
            cs.  close   ();
        }catch(Exception e){
            System.err.println("无法连接指定服务");
        }
    }
}

(2)服务器端程序

import java.io.*;
import java.net.*;
public class exp_5_4{//TCP通信,作为服务器
    public static void main(String [] args) throws IOException{
        ServerSocket ss = null; 
        try{
            ss = new   ServerSocket    (8000); 
            System.out.println("服务器开始监听8000端口的连接请求");
        }catch(IOException e){
            System.err.println("8000端口不能使用");
            System.exit(1);
        }
        Socket cs= null; 
        try{
            cs = ss.   accept       (); 
        }catch(IOException e){
            System.err.println("接收客户机端连接失败");
            System.exit(1);
        }
        DataOutputStream os = new DataOutputStream(cs.getOutputStream());
        DataInputStream is = new DataInputStream(cs.getInputStream() );
        String inputStr, outputStr;
        //输出操作
        os.writeUTF("Welcome to My Chat Server");
        os.flush();//立即将数据从输出缓存提交给网络发送
        DataInputStream stdIn =  new DataInputStream(  System.in         ); //获得键盘输入流
        //输入操作
        while((inputStr= is.   readUTF ) != null){ //接受网络数据
            System.out.println("Customer:" + inputStr); 
            System.out.print("Server:");
            outputStr = stdIn.readLine();  //接受键盘输入
            Os.  writeUTF    (outputStr); //向网络发送数据
            os.flush();
            if(outputStr.equals("bye")) break;
        }
        os.close();//流关闭
        is.close();
        cs.close();//套接字关闭
        ss.close();
    }
}
  

(3)客户端连接服务器端,并获得输入与输出流

import java.io.*;
import java.net.*;
public class exp_5_3{
    public static void main(String args[]) throws IOException{
        Socket cs = null;
        DataOutputStream os = null;   
        DataInputStream is = null;     
        try{//建立socket连接
            cs = new    Socket       ("localhost", 8000);//发出连接请求
            is = new DataInputStream(cs.  getInputStream       ());        
            os = new DataOutputStream(cs.  getOutputStream          ());    
        }catch(UnknownHostException e){
            System.err.println("不可识别的主机");
            System.exit(0);
        }catch(IOException e){
            System.err.println("无法链接到服务器的8000端口");
            System.exit(0);
        }
        DataInputStream stdIn = new DataInputStream(System.in);
        System.out.print("请输入你的用户名:");
        String username = stdIn.readLine();
        String fromServer, fromUser;
        while((fromServer = is.readUTF()) != null){          
            System.out.println("Server:" + fromServer);
            if(fromServer.equals("bye")) break;
            System.out.print("Client:");
            fromUser = stdIn.readLine();
            os.writeUTF(username + "#" +fromUser);   
            Os.  flush           ();
        }
        os.close();    
        is.close();
        stdIn.close();   
        cs.close();    
    }
}

2. 课本例2-1的PortScanner.java实验
在这里插入图片描述
(1)进行测试,给出代码过程分析及部分运行结果。
在这里插入图片描述

(2)分析可以在哪些方面进行改进,测试并给出运行结果。
① 设置连接超时:
客户端的socket构造方法请求与服务器连接时,默认情况下,会一直等待下去,直到连接成功,或者出现异常,Socket构造方法请求连接时,受底层网络的传输速度影响,可能会处于长时间的等待状态。所以,设置连接超时可以限定等待连接的时间。
代码:
在这里插入图片描述
在这里插入图片描述
② 使用多线程进行端口扫描:
课本例2-1给的程序是利用单线程来进行端口扫描的,效率较为低下,因此可以使用多线程的方式来进行端口扫描;
代码:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
3.课本例3-5 EchoServer.java,例3-6ThreadPool.java代码分析。
(1)这两个例子给出了服务端实现多线程的两种主要方法,测试两种方法的性能,分析两种实现方法的异同及其优缺点;
答:EchoServer接收到一个客户连接,就与客户进行通信,通信完毕后断开连接,然后再接受下一个客户连接,假如同时有多个客户请求连接,这些客户就必须排队等候EchoServer的响应。
ThreadPool采用线程池,不断地从工作队列中取出任务,然后执行任务,当工作线程执行完一个任务时,就会继续执行工作队列中的下一个任务。
相同之处:都采用多线程的方式来进行不同客户端socket
的事件处理
不同之处:EchoServer采用的是使用时创建线程,完成后销毁线程的方式,ThreadPool采用的是通过线程池来复用线程的方式进行多线程处理;
EchoServer优点:为每个客户分配一个工作线程。
EchoServer缺点:服务器创建和销毁工作线程的开销很大;
活动的线程也消耗系统资源;如果县城数目固定,每个线程有很长的生命周期,那么线程的切换也是相对固定的。
ThreadPool优点:减少了创建和销毁线程的次数;方便调整线程池中线程的数目。
ThreadPool缺点:需要分配核心线程数量以及创建LinkedList等集合来存储事件到来的前后顺序。
(2)画出两种实现方法中使用的主要类及其相互关系。

在这里插入图片描述
(3)对上述例子进行分析,自行设计一个多线程的服务器程序及其客户端程序,说明其主要功能,实现方法及运行结果。
答:主要功能:创建多线程服务器,实现客户端连接。
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值