TCP通信:
Socket --相当于“虚拟链路两端的插座”。Socket负责完成通信。
ServerSocket --它只负责“接收”连接。它用于产生Socket。
服务器端编程:
1) 创建ServerSocket 对象,该对象负责“接收”连接。
2) 如果客户端有连接,ServerSocket 对象调用accept()方法返回一个Socket。
3) 通过IO流读取对方的信息,也可向对方发送数据。
客户端编程:
1) new Socket()来建立与远程服务器的连接。
2) 通过IO流读取对方的信息,也可向对方发送数据。
举列说明1(简单通信):
- /**
- *@authorlhy
- *@description服务器端
- */
- publicclassServerTest{
- publicstaticvoidmain(String[]args){
- PrintStreamps=null;
- try{
- //ServerSocket只负责“接收”连接,20000为端口号(标识该应用程序)
- ServerSocketss=newServerSocket(20000);
- System.out.println("服务器端等待连接...");
- //接收连接,它会阻塞线程
- Socketsocket=ss.accept();
- //----------------------下面统一面向IO编程--------------------------//
- ps=newPrintStream(socket.getOutputStream());
- ps.println("ServerTest你好");
- }catch(IOExceptione){
- e.printStackTrace();
- }finally{
- ps.close();
- }
- }
- }
- /**
- *@authorlhy
- *@description客户端
- */
- publicclassClientTest{
- publicstaticvoidmain(String[]args){
- BufferedReaderbr=null;
- try{
- Socketsocket=newSocket("192.168.0.8",20000);
- //----------------------下面统一面向IO编程--------------------------//
- br=newBufferedReader(newInputStreamReader(socket
- .getInputStream()));
- Stringline=null;
- while((line=br.readLine())!=null){
- System.out.println(line);
- }
- }catch(IOExceptione){
- e.printStackTrace();
- }finally{
- try{
- br.close();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- }
- }
举列说明2(控制台多人聊天):
服务器端:
- publicclassServerTest{
- staticSet<Socket>clients=Collections
- .synchronizedSet(newHashSet<Socket>());
- publicstaticvoidmain(String[]args){
- ServerSocketss=null;
- try{
- ss=newServerSocket(20000);
- System.out.println("服务器端等待连接...");
- while(true){
- //接收连接,它会阻塞线程
- Socketsocket=ss.accept();
- clients.add(socket);
- //启动线程
- newServerThread(socket).start();
- }
- }catch(IOExceptione){
- e.printStackTrace();
- }finally{
- try{
- ss.close();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- }
- }
- //单独封装一个线程类
- classServerThreadextendsThread{
- privateSocketsocket;
- publicServerThread(Socketsocket){
- this.socket=socket;
- }
- @Override
- publicvoidrun(){
- BufferedReaderbr=null;
- try{
- while(true){
- //----------------------下面统一面向IO编程--------------------------//
- br=newBufferedReader(newInputStreamReader(socket
- .getInputStream()));
- Stringline=null;
- while((line=br.readLine())!=null){
- for(Sockets:ServerTest.clients){
- PrintStreamps=newPrintStream(s.getOutputStream());
- ps.println(line);//输出各个客户端对应的Socket
- }
- }
- }
- }catch(IOExceptione){
- e.printStackTrace();
- }finally{
- try{
- br.close();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- }
- }
客户端:
- publicclassChatServer{
- //定义一个线程安全的Set集合
- publicstaticSet<Socket>clients=Collections
- .synchronizedSet(newHashSet<Socket>());
- publicstaticvoidmain(String[]args)throwsIOException{
- //ServerSocket只负责“接受”连接,不能通信
- //该服务器程序就在30002端口监听
- ServerSocketss=newServerSocket(20000);
- System.out.println("服务器等待连接...");
- while(true){//这样保证每个客户端有一条线程
- //接受连接。它会阻塞线程
- Socketsocket=ss.accept();//只要连接成功,它会返回socket
- clients.add(socket);//每次客户端连接进来,就将该客户端添加到clients集合中
- System.out.println("当前用户数量:"+clients.size());
- newServerThread(socket).start();
- }
- }
- }
- classServerThreadextendsThread{
- privateSocketsocket;
- publicServerThread(Socketsocket){
- this.socket=socket;
- }
- @Override
- publicvoidrun(){
- //-----原來读文件,现在改为读网络,只要改节点
- try{
- BufferedReadersocketBr=newBufferedReader(newInputStreamReader(
- socket.getInputStream()));
- Stringline=null;//line代表从网络中读取数据
- while((line=socketBr.readLine())!=null){
- for(Iterator<Socket>it=ChatServer.clients.iterator();it
- .hasNext();){
- Sockets=it.next();
- try{
- PrintStreamps=newPrintStream(s.getOutputStream());
- ps.println(line);//输出到各客户端对应的socket
- }catch(SocketExceptionex){
- it.remove();//捕获到该socket的异常,即表明Socket已经断开
- System.out.println("当前用户数量:"+ChatServer.clients.size());
- //ex.printStackTrace();
- }
- }
- }
- }catch(SocketExceptionse){
- ChatServer.clients.remove(socket);
- System.out.println("当前用户数量:"+ChatServer.clients.size());
- }catch(Exceptione){
- e.printStackTrace();
- }
- }
- }
小结:
System.in :读取键盘输入。包装方法:BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket.getInputStream():读取网络。包装方法:BufferedReadersocketBr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
socket.getOutputStream():写入(输出到)网络。包装方法:PrintStream socketOut = new PrintStream(socket.getOutputStream());
System.out:输出到屏幕。
下面以之前IO讲的一张图来结束: