




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、案例:实现学生成绩查询系统的实时互动案例:实现学生成绩查询系统的实时互动聊天功能聊天功能 。 浙江工业大学浙江工业大学 计算机学院计算机学院赵小敏赵小敏涉及知识点n1、线程程序、线程程序的创建n2、线程的生命周期、线程的生命周期n3、多线程的同步处理、多线程的同步处理n4、基于、基于TCP的网络程序设计的网络程序设计8.1线程的创建n编写多线程程序是为了提高资源的利用率或提高编写多线程程序是为了提高资源的利用率或提高程序的运行效率或更好地监控程序的运行过程。程序的运行效率或更好地监控程序的运行过程。n编写线程的方法:编写线程的方法:1.通过实现接口通过实现接口java.lang.Runnabl
2、e创建线程创建线程2.通过继承类通过继承类java.lang.Thread创建线程创建线程1、通过实现、通过实现Runnable接口创建线程接口创建线程nRunnable 接口只提供了一个接口只提供了一个public void run( )方法。方法。n创建线程的方法:创建线程的方法:定义一个类实现定义一个类实现Runnable接口。接口。将该类的实例作为参数传给将该类的实例作为参数传给Thread类的一个类的一个构造函数,从而创建一个线程。构造函数,从而创建一个线程。例:用用Runnable创建线程的示例创建线程的示例1.public class ThreadTest2. public st
3、atic void main(String args )3.Thread t1 = new Thread( new Hello( ) );4.Thread t2 = new Thread( new Hello( ) );5.t1.start( );6.t2.start( );7.8.9.class Hello implements Runnable10. int i ;11. public void run( )12.while( true)13.System.out.println(Hello:+i+);14.if (i=5) break ;15.16. 17. 2、通过继承类、通过继承类T
4、hread创建线程创建线程nThread 类本身实现了类本身实现了Runnable接口。接口。n在在Thread类中,类中,run方法被实现为空方法。方法被实现为空方法。nThread中的构造方法:中的构造方法:public Thread( );public Thread(String name)public Thread(Runnable target)public Thread(Runnable target, String name)public Thread(ThreadGroup group, Runnable target)public Thread(ThreadGroup gro
5、up, String name)public Thread(ThreadGroup group, Runnable target, String name)通过继承通过继承Thread类来创建线程的步骤类来创建线程的步骤(1)通过继承通过继承Thread类,重写类,重写run( )方法来定义线程体。方法来定义线程体。public class Counter extends Thread public void run( ) (2)创建该子类的对象创建线程。创建该子类的对象创建线程。创建与运行线程:创建与运行线程:Counter ThreadCounter = new Counter( );Th
6、readCounter.Start( );例例2:通过继承:通过继承Thread类创建线程类创建线程1.public class ThreadTest2 2. public static void main(String args )3. Hello t1 = new Hello( );4. Hello t2 = new Hello( );5. t1.start( );6. t2.start( );7. 8.9.class Hello extends Thread10. int i ;11. public void run( )12.while( true)13.System.out.prin
7、tln(Hello+i+);14.if (i=5) break ;15.16. 17. 两种创建线程方法比较两种创建线程方法比较n实现实现Runnable接口的优势:接口的优势:q符合符合OO设计的思想。设计的思想。q便于用便于用extends继承其它类。继承其它类。n采用继承采用继承Thread类方法的优点:程序代码更简单。类方法的优点:程序代码更简单。n提倡采用第一种方式。提倡采用第一种方式。n通过通过Thread实例的实例的start(),一个,一个Thread的实例只能的实例只能产生一个线程产生一个线程n Runnable的实例是可运行的,但它自己并不能直接的实例是可运行的,但它自己并
8、不能直接运行,它需要被运行,它需要被Thread对象来包装才行运行对象来包装才行运行 ,但同同一实例一实例(Runnable实例实例)可产生多个线程可产生多个线程例例3:两种创建线程方法比较:两种创建线程方法比较1.class MyThread extends Thread2. public int x = 0;3. public void run()4. System.out.println(+x);5. 6.7.class R implements Runnable8. private int x = 0;9. public void run()10. System.out.println
9、(+x);11. 12.例例3:两种创建线程方法比较:两种创建线程方法比较(续续)13.public class TestMyThread 14. public static void main(String args) throws Exception 15. for(int i=0;i10;i+)16. Thread t = new MyThread();17. t.start();18. 19. Thread.sleep(5000);/休眠休眠5s,让上面的线程运行完成让上面的线程运行完成 20. R r = new R();21. for(int i=0;i10;i+)22. Thre
10、ad t = new Thread(r);23. t.start();24. 25. 26.8.2线程的生命周期线程的生命周期就绪就绪运行运行阻塞阻塞死亡死亡阻塞在阻塞在对象锁池对象锁池阻塞在阻塞在对象等待池对象等待池新建新建Start( )线程调度yield( )Sleep() or join( )run( ) endswait( )Synchronized( )Lock可用notify( )interrupt( )Sleep( ) timeoutThread joins orinterrupt线程的基本控制方法nsleep( )nsetPriority()和和getPriority()ny
11、ield( )njoin( )ninterrupt()ncurrentThread()nisAlive()nisDaemon()和和setDaemon()nstop() 过时过时类类Thread的方法的方法sleep( )方法方法n该方法用来使一个线程暂停运行一段固定的时间。该方法用来使一个线程暂停运行一段固定的时间。n在线程睡眠时间内,将运行别的线程。在线程睡眠时间内,将运行别的线程。nsleep( ) 结束后,线程将进入结束后,线程将进入就绪就绪(Runnable)状态。状态。nsleep()方法的格式有以下两种:方法的格式有以下两种:static void sleep(int mills
12、) throws InterruptedException /休眠时间以休眠时间以ms为单位为单位static void sleep(long millis, int nanos) throws InterruptedException /休眠时间,指毫秒数与纳休眠时间,指毫秒数与纳秒数之和秒数之和例例4:每隔一秒钟打印一个数字到屏幕每隔一秒钟打印一个数字到屏幕1.public class Timer extends T time=1;3.public Timer(int time)4.this.time=time;5.6. public void run()7. try8
13、. for(int i=1;i=time;i+) 9. Thread.sleep(1000);10. System.out.println(i);11. 12. catch(InterruptedException e)13. System.out.println(e.toString();14. 15. 16.public static void main(String args)17.Timer timer=new Timer(10);18.timer.start();19. 20.线程优先级控制:线程优先级控制:setPriority()和和getPriority()n某一时刻一个某一时
14、刻一个CPUCPU只执行一个线程只执行一个线程, ,调度策略为调度策略为固定优先级调度策略,优先级高的先被调度固定优先级调度策略,优先级高的先被调度l级别有级别有: MIN_PRIORITY : MIN_PRIORITY 最小值为最小值为1 1 NORM_PRIORITY NORM_PRIORITY 默认值,值为默认值,值为5 5 MAX_PRIORITY MAX_PRIORITY 最大值为最大值为1010l利用利用setPrioritysetPriority()()和和getPrioritygetPriority()()方法设置方法设置和获得线程的优先级和获得线程的优先级多线程的执行顺序多线
15、程的执行顺序n多个线程运行时,调度策略为固定优先级调度,多个线程运行时,调度策略为固定优先级调度,级别相同时,由操作系统按时间片来分配。级别相同时,由操作系统按时间片来分配。n下面给出的例子中下面给出的例子中,共运行三个线程共运行三个线程,它们做同它们做同样的事样的事, 每次打印循环次数和自己的序列号每次打印循环次数和自己的序列号,运运行结果表明行结果表明,它们并不是连续运行的。它们并不是连续运行的。例例5:多个进程运行时执行顺序是交叉的:多个进程运行时执行顺序是交叉的1.class MultiThread extends Thread2. int threadNum;3. public st
16、atic void main(String args)4. multithread array=new MultiThread 3;5. for (int i=0;i3;i+) 6. arrayi=new MultiThread (i+1);7. for (int i=0;i3;i+) 8. arrayi.start(); 9. 10. MultiThread (int SerialNum)11. super(); 12. threadNum=SerialNum; 13. 例例5:多个进程运行时执行顺序是交叉的:多个进程运行时执行顺序是交叉的14. public void run()15. i
17、nt MySerialNum=0;16. for(int j=1;j=10;j+)17. MySerialNum+;18. try19. Thread.sleep(1000);20. catch(Exception e)21. System.out.println(e.toString();22. 23. System.out.println(loop: + MySerialNum);24. System.out.println(thread:+threadNum+ bye.); 25. 26. 27.yield( )方法方法n调用该方法将调用该方法将CPU让给具有与当前线程相同让给具有与当前
18、线程相同优先级的线程。优先级的线程。n如果没有同等优先级的线程是就绪如果没有同等优先级的线程是就绪(Runnable)状态,状态,yield( )方法将什么也不做。方法将什么也不做。yield( )方法方法n调用该方法将调用该方法将CPU让给具有与当前线程相同优让给具有与当前线程相同优先级的线程。先级的线程。n如果没有同等优先级的线程是如果没有同等优先级的线程是Runnable状态,状态,yield( )方法将什么也不做。方法将什么也不做。join( )方法方法nt.join( )方法使当前的线程等待,直到方法使当前的线程等待,直到 t 结束为止,结束为止,线程恢复到线程恢复到运行运行(run
19、nable)状态。状态。n有三种调用格式:有三种调用格式:join():如当前线程发出调用如当前线程发出调用t.join(),则当前线程将,则当前线程将等待线程等待线程 t结束后在继续执行。结束后在继续执行。join(long millis):如当前线程发出调用如当前线程发出调用t.join(),则当,则当前线程将等待线程前线程将等待线程t结束或最多等待结束或最多等待mills毫秒后在继毫秒后在继续执行。续执行。join(long millis,long nanos) throws InterruptedException例6: join( )方法的使用例子方法的使用例子1.public cl
20、ass ThreadJoinTest 2. public static void main(String args )3.int i=0;4.Hello t = new Hello( );5.t.start( );6.while( true)7.System.out.println(Good Morning+i+);8.if (i = 2 & t.isAlive()9. System.out.println(Main waiting for Hello!);10. try11. t.join( ); /等待等待t运行结束运行结束12. catch(InterruptedExceptio
21、n e)13. 14. 15.if (i=5) break ;16.17.18.例6: join( )方法的使用例子方法的使用例子(续续)19.class Hello extends Thread20. int i ;21. public void run( )22.while( true)23.System.out.println(Hello+i+);24.if (i=5) break ;25.26. 27. interrupt()方法:中断线程方法:中断线程n如果一个线程如果一个线程t在调用在调用sleep()、join()、wait()等方法被阻塞时,则等方法被阻塞时,则err
22、upt()方法将中断方法将中断t的阻塞状态,并将接收到的阻塞状态,并将接收到InterruptException对象。对象。currentThread()方法:获取当前线程方法:获取当前线程nThread 类的静态方法类的静态方法currentThread( )返回返回当前线程。当前线程。isAlive()方法方法n当线程的状态未知时,用当线程的状态未知时,用isAlive()确定线程是确定线程是否活着。否活着。n返回返回true 意味着线程已经启动,但还没有运意味着线程已经启动,但还没有运行结束。行结束。isDaemon()和和setDaemon()方法方法n线程可分为守护线程与用户线程线程
23、可分为守护线程与用户线程n当一个程序中只有一个守护线程在运行,程序会当一个程序中只有一个守护线程在运行,程序会立即退出;如果一个程序还有正在运行的用户线立即退出;如果一个程序还有正在运行的用户线程,该程序不会中止。程,该程序不会中止。n判断一个线程是用户线程还是守护线程,用判断一个线程是用户线程还是守护线程,用isDaemon()方法方法n将一个线程设置为守护线程用将一个线程设置为守护线程用setDaemon()方法方法结束线程结束线程stop()n线程完成运行并结束后,将不能再运行。线程完成运行并结束后,将不能再运行。n除正常运行结束外,还可用其他方法控制使其除正常运行结束外,还可用其他方法
24、控制使其停止。停止。q用用stop( )方法方法,已过时已过时 强行终止线程,容易造成线程的不一致。强行终止线程,容易造成线程的不一致。q使用标志使用标志flag。 通过设置通过设置flag 指明指明run( )方法应该结束。方法应该结束。例例7:结束线程的控制:结束线程的控制8.3 多线程的同步处理多线程的同步处理n多个线程在并发地运行时可能共用资源。多个线程在并发地运行时可能共用资源。n多个线程并发执行时,线程的相对执行顺序是多个线程并发执行时,线程的相对执行顺序是不确定的;不确定的;n多线程对共享数据操作时,这种线程运行顺序多线程对共享数据操作时,这种线程运行顺序的不确定性将会产生执行结
25、果的不确定性,使的不确定性将会产生执行结果的不确定性,使共享数据的一致性被破坏共享数据的一致性被破坏n多线程同步处理的目的是为了让多个线程协调地多线程同步处理的目的是为了让多个线程协调地并发工作。并发工作。例8:由多个并发线程共享内存引发的问题:加减法失败1.public class ThreadSum extends Thread2. public static int data=0;3. public static int times=10000;4. public int ID;5. public boolean done;6. ThreadSum(int id)7. ID=id;8.
26、public void run( ) done=false; int d= (ID % 2=0) ? 1 : -1); System.out.println(运行线程运行线程: + ID + (增量为增量为: + d + ); for(int i=0; itimes; i+)2121 for(int j=0; jtimes; j+)2222 data+=d;2323 done=true;2424 System.out.println(结束线程结束线程: + ID);2525 / 方法方法run结束结束2626 2727 public static void main(String args )
27、2828 ThreadSum t1 = new ThreadSum(1);2929 ThreadSum t2 = new ThreadSum(2);3030 t1.done=false;3131 t2.done=false;3232 t1.start( );3333 t2.start( );3434 / 等待两个线程运行结束等待两个线程运行结束3535 while ( !t1.done | !t2.done ) 3636 ; 3737 System.out.println(结果结果: data= + data);3838 3939 加减法失败程序分析n每次运行的结果不一致。每次运行的结果不一致
28、。nmain方法中创建了两个线程方法中创建了两个线程t1和和t2,t1.done和和t2.done是两个不同的变量,占用不同的内存空间,是两个不同的变量,占用不同的内存空间,而而data是是t1和和t2共享的内存数据。共享的内存数据。n线程线程t1对对data增加增加timestimes次,每次加次,每次加1,而而t2对对data减小减小timestimes次,每次减次,每次减1。若。若t1加加1的操作和的操作和t2减减1的操作都正确完成,则的操作都正确完成,则data的结果值为的结果值为0n但但data的值不为的值不为0,是因为两个线程并发运行造,是因为两个线程并发运行造成的,当出现两个线程
29、同时要改变成的,当出现两个线程同时要改变data值时,对值时,对data的值加的值加1或减或减1的操作就有可能无法完成。的操作就有可能无法完成。多线程同步的基本原理n多个并发线程之间共用资源,则需要进行同步处理多个并发线程之间共用资源,则需要进行同步处理对象锁的概念对象锁的概念n一个程序的各个并发线程中对同一个对象进行访问的一个程序的各个并发线程中对同一个对象进行访问的代码段,成为临界区。代码段,成为临界区。n在在java语言中,临界区可以是一个语句块或一个方法,语言中,临界区可以是一个语句块或一个方法,并且用并且用synchronized关键字标识。关键字标识。n临界区的控制是通过对象锁进行
30、的。临界区的控制是通过对象锁进行的。Java平台将每平台将每个由个由synchronized(someObject) 语句指定的对象语句指定的对象someObject设置一个锁,称为设置一个锁,称为对象锁对象锁。n对象锁是一种独占的排它锁,即一个线程获取对象的对象锁是一种独占的排它锁,即一个线程获取对象的锁后,便拥有该对象的操作权,其它任何线程不能对锁后,便拥有该对象的操作权,其它任何线程不能对该对象进行任何操作。该对象进行任何操作。同步方法和同步语句块同步方法和同步语句块n同步方法:用关键字同步方法:用关键字synchronized 修饰方法修饰方法n同步语句块的定义格式如下同步语句块的定义
31、格式如下:synchronized (引用类型的表达式引用类型的表达式) 语句块语句块方法方法wait/notify/notifyAlln方法方法wait:在其他线程调用此对象的在其他线程调用此对象的 notify() 方法或方法或 notifyAll() 方法前,导致当前线程等方法前,导致当前线程等待。待。n方法方法notify:唤醒在此对象监视器上等待的单唤醒在此对象监视器上等待的单个线程个线程n方法方法notifyAll:唤醒在此对象监视器上等待的唤醒在此对象监视器上等待的所有线程。所有线程。 线程死锁的防治n如果程序中多个线程互相等待对方持有的锁,如果程序中多个线程互相等待对方持有的锁
32、,而在得到对方锁之前都不会释放自己的锁,则而在得到对方锁之前都不会释放自己的锁,则会导致这些线程不能继续运行,这就是会导致这些线程不能继续运行,这就是死锁死锁。nJava没有检测与避免死锁的专门机制,完全没有检测与避免死锁的专门机制,完全由程序进行控制由程序进行控制nJava防治死锁的做法是:如果程序要访问多防治死锁的做法是:如果程序要访问多个共享数据,首先从全局考虑获得锁的顺序,个共享数据,首先从全局考虑获得锁的顺序,并且在整个程序中都遵守这个顺序;释放锁时,并且在整个程序中都遵守这个顺序;释放锁时,要按加锁的反序释放。要按加锁的反序释放。例例9:生产者和消费者问题:生产者和消费者问题n生产
33、者和消费者模型是典型的线程同步问题,生产者和消费者模型是典型的线程同步问题,下面我们通过这个模型来说明线程同步的处理下面我们通过这个模型来说明线程同步的处理方法:方法:n使用某种资源的线程称为消费者,产生或释放使用某种资源的线程称为消费者,产生或释放这个资源的线程称为生产者。这个资源的线程称为生产者。1.生产者生成生产者生成10个整数(个整数(09),存储到一个共享对),存储到一个共享对象中,并把它们打印出来。象中,并把它们打印出来。2.每生成一个数就随机休眠每生成一个数就随机休眠0100毫秒,然后重复这毫秒,然后重复这个过程。个过程。3.一旦这一旦这10个数可以从共享对象中得到,消费者将尽可
34、个数可以从共享对象中得到,消费者将尽可能快地消费这能快地消费这10个数,即把它们取出后打印出来。个数,即把它们取出后打印出来。生产者程序生产者程序1.public class Producer extends Thread 2. private Share shared;3. private int number;4. public Producer(Share s, int number) 5. shared=s;6. this.number=number;7. 8. public void run( ) 9. for (int i=0; i10; i+) 10. shared.put(i)
35、;11. System.out.println(“生产者生产者”+this.number+“输出的数据为:输出的数据为:+ i);12. try 13. sleep(int)(Math.random( ) * 100);14. catch (InterruptedException e) 15. 16. 17.消费者程序消费者程序1.public class Consumer extends Thread 2. private Share shared;3. private int number;4. public Consumer(Share s, int number) 5. shared
36、=s;6. this.number=number;7. 8. public void run( ) 9. int value = 0;10. for (int i=0; i10; i+) 11. value=shared.get( );12. System.out.println(“消费者消费者”+this.number+“得到的数据为:得到的数据为: value);13. 14. 15.共享资源对象共享资源对象1.public class Share 2. private int contents;3. public int get( )4. return contents;5. 6. pu
37、blic void put(int value)7. contents=value;8. 9.测试的主程序测试的主程序1.public class PCTest 2.public static void main(String args) 3.Share s=new Share( );4.Producer p=new Producer(s,1);5.Consumer c=new Consumer(s,1);6.p.start( );7.c.start( );8. 9.运行结果结果分析n我们分析一下可能发生的情况:一种情况是生产者比我们分析一下可能发生的情况:一种情况是生产者比消费者速度快,那么
38、在消费者还没有取出上一个数据消费者速度快,那么在消费者还没有取出上一个数据之前,生产者又存入了新数据,于是,消费者很可能之前,生产者又存入了新数据,于是,消费者很可能会跳过上一个数据。另一种情况则相反,当消费者比会跳过上一个数据。另一种情况则相反,当消费者比生产者速度快,消费者可能两次取出同一个数据。生产者速度快,消费者可能两次取出同一个数据。n这两种情况不是我们所希望的。我们希望生产者存入这两种情况不是我们所希望的。我们希望生产者存入一个数,消费者取出的就是这个数。为了避免上述情一个数,消费者取出的就是这个数。为了避免上述情况发生,就必须锁定生产者线程,当它向共享对象中况发生,就必须锁定生产
39、者线程,当它向共享对象中存储数据时禁止消费者线程从中取出数据,反之也一存储数据时禁止消费者线程从中取出数据,反之也一样。将共享对象样。将共享对象Share中的中的put和和get分别定义为同步分别定义为同步化方法就可达到这个目的。化方法就可达到这个目的。解决方法解决方法共享资源对象实现同步化共享资源对象实现同步化1.public class Share 2. private int contents;3. private boolean available=false;4. public synchronized int get( ) 5. while (available=false) 6.
40、 try 7. wait( );/线程等待并暂时释放共享数据对象的锁8. catch (InterruptedException e) 9. 10. available=false;11. notifyAll( );/释放对象锁,通知正在等待的线程重新占有锁并运行12. return contents;13. 解决方法解决方法共享资源对象实现同步化共享资源对象实现同步化(续续)14. public synchronized void put(int value) 15. while (available=true) 16. try 17. wait( );18. catch (Interrup
41、tedException e) 19. 20. contents=value;21. available=true;22. notifyAll( );23. 24.运行结果修改后的程序分析1n修改后的修改后的Share仍利用仍利用put和和get方法来写入和读取数据,但增加方法来写入和读取数据,但增加了了wait和和notifyAll功能。功能。nwait使线程进入短暂休眠,收到使线程进入短暂休眠,收到notifyAll的通知后会马上醒来。的通知后会马上醒来。n当消费者线程调用共享对象的当消费者线程调用共享对象的get方法时,如果生产者没有写入数方法时,如果生产者没有写入数据,据,availa
42、ble变量就会保持为假,线程进入循环并调用变量就会保持为假,线程进入循环并调用wait方法方法等待。等待。n一旦生产者写入了新数据,一旦生产者写入了新数据,available的值就会改变,同时生产者的值就会改变,同时生产者还会向消费者发出通知,唤醒消费者线程退出循环。还会向消费者发出通知,唤醒消费者线程退出循环。n此时,消费者线程将做两个非常重要的工作,一是把此时,消费者线程将做两个非常重要的工作,一是把available变变量改为假,二是通知生产者线程。最后,返回量改为假,二是通知生产者线程。最后,返回contents,它包含,它包含最新写入的数据。最新写入的数据。修改后的程序分析2n当生产
43、者线程第一次调用共享对象的当生产者线程第一次调用共享对象的put方法时,方法时,available变量为假,线程将跳过循环并将第一个数据变量为假,线程将跳过循环并将第一个数据写入写入contents变量,然后将变量,然后将available变量改为真值,变量改为真值,调用调用notifyAll方法通知消费者线程可以取数据了。方法通知消费者线程可以取数据了。n再次调用再次调用put方法时,如果消费者没有取走数据,方法时,如果消费者没有取走数据,available变量就会保持为真,线程将进入循环并调用变量就会保持为真,线程将进入循环并调用wait方法等待。方法等待。n一旦消费者取走上一个数据,一旦
44、消费者取走上一个数据,available的值就会改变,的值就会改变,线程也会被唤醒并退出循环,继续后面的工作。线程也会被唤醒并退出循环,继续后面的工作。n采用这样的处理方式,就可以保证消费者一直等到生采用这样的处理方式,就可以保证消费者一直等到生产者写入一个新数据后再把它取出,而生产者则一直产者写入一个新数据后再把它取出,而生产者则一直等到消费者取走上一个数据后再写入新数据。等到消费者取走上一个数据后再写入新数据。多线程问题多线程问题对多线程程序本身来说,它会对系统产生以下影响:对多线程程序本身来说,它会对系统产生以下影响:1)线程需要占用内存。线程需要占用内存。2)线程过多,会消耗大量线程过
45、多,会消耗大量CPU时间来跟踪线程。时间来跟踪线程。3)必须考虑多线程同时访问共享资源的问题,如果没必须考虑多线程同时访问共享资源的问题,如果没有协调好,就会产生令人意想不到的问题,例如可有协调好,就会产生令人意想不到的问题,例如可怕的死锁和资源竞争。怕的死锁和资源竞争。4)因为同一个任务的所有线程都共享相同的地址空间,因为同一个任务的所有线程都共享相同的地址空间,并共享任务的全局变量,所以程序也必须考虑多线并共享任务的全局变量,所以程序也必须考虑多线程同时访问全局变量的问题。程同时访问全局变量的问题。8.4 基于基于TCP的网络程序设计的网络程序设计n传输控制协议传输控制协议TCP (Tra
46、nsfer Control Protocol) 是一种基于连接的协议,可以在两是一种基于连接的协议,可以在两台计算机之间提供可靠的数据传输。台计算机之间提供可靠的数据传输。q基于连接的协议基于连接的协议q服务器端与客户端通过服务器端与客户端通过TCP协议进行通讯协议进行通讯qTCP, 反过来反过来, 运用了运用了IP协议协议qIP 协议只用来处理数据包协议只用来处理数据包TCP/IP 网络模型网络模型服务器端服务器端ServerSocket(port#)ServerSocket.accept()OutputStreamInputStreamSocket.close()客户端客户端Socket(
47、host, port#)OutputStreamInputStreamSocket.close()类类 .Socketn类类.Socket允许如下的四种基本操作允许如下的四种基本操作1. 连接到远程的机器连接到远程的机器2. 发送数据发送数据3. 接收数据接收数据4. 关闭连接关闭连接类类.Socket中的成员方法中的成员方法n构造方法构造方法ngetInputStream(): 返回该返回该socket所对应的输所对应的输入流入流ngetOutputStream():返回该返回该socket所对应的所对应的输出流输出流创建类创建类 Socket 的实例对象的实例对象n构造方法构造方法Sock
48、et() Socket(InetAddress address, int port)Socket(InetAddress address, int port, InetAddress localAddr, int localPort) Socket(String host, int port) Socket(String host, int port, InetAddress localAddr, int localPort)n示例示例: Socket javaSite = new Socket(, 80); 类类.ServerSocketServerSocket类的主要方法(1) Socke
49、t accept() throws IOException 等待客户连接,该方法将阻塞当前系统服务线程,直到连接成功。该方法返回一个套接字类对象,通过该套接字,新的服务子线程与连接的客户进行通信。(2) Void close() throws IOException 关闭套接字怎样用socket进行客户与服务器通信 Socket是两个实体之间进行通信的有效端点。通过socket可以获得源IP地址和源端口、终点IP地址和终点端口。用户可以将多个socket连入同一个端口,以便对于单个端口可以有多个连接。 通过socket客户/服务器编程可以创建一个能被许多人使用的分布式程序,并且所有客户均可以用
50、统一的前端进行工作,并与服务器进行通信。 与服务器通信必须具备三个条件 n服务器程序n客户程序n连接它们的socket程序 ServerSocket类类 n它的实例使服务器能够检测到指定端口的信息它的实例使服务器能够检测到指定端口的信息 naccept()方法可以使服务器检测到指定端口的方法可以使服务器检测到指定端口的活动活动 n服务器还负责检测要求与它连接的客户。服务器还负责检测要求与它连接的客户。 Socket类 ngetInputStream()和和getOutStream()方法来方法来发送和捕捉数据。发送和捕捉数据。 try /传递给它一个整数作为服务器指定可以使用的给定端口传递给它
51、一个整数作为服务器指定可以使用的给定端口 ServerSocket myServerSocket=new ServerSocket(80); Socket mySocket=myServerSocket.accept(); /检测端口的活动检测端口的活动 catch(Exception e) Accept()方法直到接收到用户的连接请求,才继续执行中断的执行程序。一旦客户的连接成功,mySocket就代表该连接,并且可以发送和接收数据。 最后,我们看一看客户是怎样请求连接的。其连接方法如下: try Socket mySocket=new Socket(,80); catch(Exceptio
52、n e ) Socket类 (一)TCP协议通信的服务器方实现(1) 假设服务器工作在端口8000上,ServerSocket svrsoc ServerSocket(8000)Socket socsvrsoc.accept();/监视端口8000的连接请求(2) 打开与soc绑定的输入/输出流:In=new BufferedReader(new InputStreamRead(soc.getInputStream();/在套接字soc上绑定的输入流基础上构造BufferedReader对象TCP协议通信的服务器方实现(续)out=new PrintWrite(new bufferedWrit
53、e(new OutputStreamWrite(soc.getOutputStream(),true);/在套接字soc上绑定的输出流基础上构造PrintWrite对象服务器使用in和out两个实例从客户接收输入信息和向客户程序发信息,同样,在客户端也应该建立这两个对象,用来与服务器程序进行双向通信。(一) TCP协议通信的服务器方实现(续)(3) 获取客户机的IP地址,并在服务器窗口中显示客户机的地址信息:clientIP=soc.getInetAddress();System.out.println(“Clients IP address:”+clientIP);(4) 读入一行客户的输入
54、,并回显该行 String strin.readLine(); while(!str.equals(“quit”); System.out.println(“Client said:”+str); str=in.readLine(); (一) TCP协议通信的服务器方实现(续)(5) 不断循环以上代码,直到客户输入“quit”为止。System.out.println(“Client want to leave.”);finall in.close(); out.close(); soc.close(); svrsoc.close();(二) TCP协议通信的客户方实现(1)创建一个指向固定主
55、机的固定端口的Socket: Socket socnew Socket(“localhost”,8000);(2) 从Socket对象中获取与其绑定的输入和输出流In=new BufferedReader(new InputStreamRead(soc.getInputStream();out=new PrintWrite(new bufferedWrite(new OutputStreamWrite(soc.getOutputStream(),true);(二) TCP协议通信的客户方实现(续)(3)建立输入/输出流后,从服务器读取发来的”welcome!”信息,显示在窗口:Strin=in
56、.readLine();System.out.println(“Server said:”+strin);(二) TCP协议通信的客户方实现(续)(4)客户向服务器发送的数据流从键盘获取byte bmsg=new byte200;System.in.read(bmsg); /从键盘读入bmsgString msg=new String(bmsg,0); /byte型转String型Msg=msg.trim(); /删除msg两边的空格(二) TCP协议通信的客户方实现(续)(5)当键盘输入不是“quit”时,将键盘输入的数据写入输出流中,并发送出去,然后继续从键盘获取输入数据,不断循环,直到输
57、入“quit”时,先将其传送给服务器,然后关闭输入/输出流和Socket:out.println(strout);In.close();out.close();soc.close();System.exit(0);一个简单的客户端/服务器程序1.import .*; 2.import java.io.*; 3.import java.lang.*; 4.public class myserver 5. public static void main(String args) 6. ServerSocket server; 7. Socket socket; 8. String s; 9. In
58、putStream Is; 10. OutputStream Os; 11. DataInputStream DIS; 12. PrintStream PS; 13. try 14. server=new ServerSocket(4321); 15. socket=server.accept();16. System.out.println(server ok); 17. System.out.println(*); 18. System.out.println(); 19. Is=socket.getInputStream(); 20. Os=socket.getOutputStream(
59、); 21. DIS=new DataInputStream(Is); 22. PS=new PrintStream(Os); 23. DataInputStream in=new DataInputStream(System.in); 24. while(true) 25. System.out.println(); 26. System.out.println(please wait clients message.); 27. System.out.println(); 28. s=DIS.readLine(); 29. System.out.println(client said:+s
60、); 30. if(s.trim().equals(BYE)break; 31. System.out.print(you say:); 32. s=in.readLine(); 33. PS.println(s); 34. if(s.trim().equals(BYE)break; 35. 36. DIS.close(); 37. PS.close(); 38. Is.close(); 39. Os.close(); 40. socket.close(); 41. catch(Exception e) 42. System.out.println(Error:+e); 43. /catch44. /
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 小学三年级数学万以内加减法练习题
- 超市店长培训
- 大学生文明知识
- 电子显示屏用保护膜-编制说明(征求意见稿)
- 人教宁夏 九年级 下册 语文 第五单元《 屈原(节选)》习题课 课件
- 2023-2024年广东省梅县区设备监理师之设备工程监理基础及相关知识通关秘籍题库含答案(培优A卷)
- 人教河南 九年级 下册 语文 第二单元《 孔乙己》习题课 课件
- 人教山西 九年级 下册 语文 第六单元《 陈涉世家》习题课 课件
- 小学语文三年级上册同音字组词(含答案)
- 进修神外ICU汇报护理
- 2024年四川省公务员《申论(县乡)》试题真题及答案
- 2025年度事业单位招聘考试公共基础知识模拟试卷及答案(共四套)
- 创业要点计划月历表书项目策划(25篇)
- 富源县中劲鸿泰贸易有限公司墨红镇东兴煤矿矿山地质环境保护与土地复垦方案
- 酒店Opera前台操作流程
- 专题07 综合性学习【知识精研】中考语文二轮复习
- 2025年江西陶瓷工艺美术职业技术学院单招职业技能测试题库1套
- 《老年肺炎临床诊断与治疗专家共识(2024年版)》临床解读
- 人教版 八年级英语下册 Unit 2 单元综合测试卷(2025年春)
- 2025年无锡商业职业技术学院高职单招高职单招英语2016-2024历年频考点试题含答案解析
- 2025年中国金属加工液市场调查研究报告
评论
0/150
提交评论