2 Socket通信程序设计通信程序设计文志强计算机与通信学院基本内容2.1 Socket通信原理通信原理2.2 Socket 网络编程网络编程2.3 项目实战项目实战 2.1 Socket通信原理IP地址:主机标识端 口:服务类型Socket =IP(address)+Port(server)应用程序IP地址 端口TCP/UDP协议SocketA 机应用程序IP地址端口TCP/UDP协议SocketB 机 套接字通讯首先强调发送方和接收方的区别,同时也明确服务器和客户机之间的不同 一个客户机必须知道服务器的地址和端口,以便进行申请连接 一个服务器从它接收到的数据报文中读取客户端的地址和端口 套接字通过,确定服务器和客户机的地址和端口以及协议,利用java.io实现数据的传输Socket程序基本机理Java-Internet语言具备强大网络通信功能基于套接字(Socket)通信方式流套接字TCP协议协议(Transmission Control Protocol)UDP协议协议(User Datagram Protocol)数据报套接字 Java的的Socket属于流式套接字通信,采用属于流式套接字通信,采用TCP协议,提协议,提供面向连接的服务,实现可靠的通信。
供面向连接的服务,实现可靠的通信Java Socket J提供两个类,实现Socke通信:Socket编程属低层次网络编程,功能强大,相对URL网络编程提供更多的功能和更灵活的控制,复杂度较高ServerSocket -服务器端 Socket -客户端通 操作TCP 套接字的发送和接收需要借助java.io包的 InputStream /OutputStream 完成,分别通过方法实现:Socket.getInputStream()/Socket.getOutputStream()Socket/ServerSocket构造函数 Socket()通过系统默认类型的 SocketImpl 创建未连接套接字 Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号 Socket(InetAddress address,int port,InetAddress localAddr,int localPort)创建一个套接字并将其连接到指定远程端口上的指定远程地址 Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号 Socket(String host,int port,InetAddress localAddr,int localPort)创建一个套接字并将其连接到指定远程主机上的指定远程端口ServerSocket()创建非绑定服务器套接字 ServerSocket(int port)创建绑定到特定端口的服务器套接字 ServerSocket(int port,int backlog)利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号 ServerSocket(int port,int backlog,InetAddress bindAddr)使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器 Socket/ServerSocket主要方法InetAddress getInetAddress()返回套接字连接的地址InputStream getInputStream()返回此套接字的输入流InetAddress getLocalAddress()获取套接字绑定的本地地址int getLocalPort()返回此套接字绑定到的本地端口OutputStream getOutputStream()返回此套接字的输出流int getPort()返回此套接字连接到的远程端口void close()关闭此套接字Socket accept()服务器侦听并接受到此套接字的连接void close()关闭此套接字Java Socket通信原理 1.通讯的两个程序分别为Client/Server。
Client端程序申请连接,Server端程序监听所有端口,判断是否有Client程序的服务请求2.当Client程序请求某端口连接时,Server程序将“套接字”连接到该端口上,此时,Client/Server程序建立一个虚连接3.Client程序向套接字写入请求,Server程序处理请求并把处理结果通过套接字送回给Client4.通信结束时,拆除所建的虚拟连接Socket网络通信程序由三个基本部分组成:(1)建立连接:通信双方在通信开始之前,建立一条专用的虚拟连接通道(2)数据通信:利用虚拟连接通道传送数据信息进行通信(3)拆除连接:通信结束时,将所建的虚拟连接拆除2.2 Socket 网络编程 Server端Client端service=ServiceSocket(port_number)创建service对象,以TCP服务实现端口监听socket=ServerSocket.accept()创建socke对象,接收用户访问请求Socket=Socket(port_number)创建socke对象,建立连接,发送访问请求InputStream Socket对象输入流OutputStream Socket对象输出流通过socke对象实现与Client端数据传输OutputStream Socket对象输出流InputStream Socket对象输入流通过socke对象,实现与Servert端数据传输socket.close()关闭Socke关闭结束与Client端的连接service.close()关闭监听程序socket.close()关闭Socke结束与Server端的连接(1)建立连接(2)数据通讯(3)拆除连接Socke通信机制 OutputStream获得获得Socket对象输出流对象输出流Socke通信机制 建立Socket连接通过流传输数据服务端联结成功联结成功获得已连接的获得已连接的Socket对象对象Socket(host,port)Socket(host,port)创建创建Socket对象对象向指定主机端口发出连接请向指定主机端口发出连接请求求客户端Socket对象ServerSocket对象InputStream获得获得Socket对象输入流对象输入流申请连接ServiceSocket.close()停止提供停止提供TCP连接服务连接服务一个一个ServerSocket对象和一个对象和一个Socket对象对象一个一个Socket对象对象Socket.close()关闭关闭TCP连接连接ServiceSocket(port)创建创建ServiceSocke对象对象,提供提供TCP连接服务连接服务accept()在指定的端口监听客户端请求联结创建在指定的端口监听客户端请求联结创建InputStream获得获得Socket对象输入流对象输入流Socket.close()关闭关闭TCP连接连接OutputStream获得获得Socket对象输出流对象输出流ServerSocket对象访问监听1.利用构造函数创建ServerSocke/Socket两两个个对象,建立双向连接2.引入异常处理机制异常处理机制3.3.建立建立I/O流流4.实现读/写数据流5.释放连接ServerSocket程序程序基本框架结构基本框架结构Java ServerSocketServerSocketSocket创建一个服务器的典型工作流程:(1)创建一个指定端口的ServerSocket对象。
2)ServerSocket对象调用accept()方法创建一个Socket对象实现端口监听连接请求但accept()收到客户端连接请求,且返回连接客户端与服务器的Socket对象,则双方的虚电路建立完成3)调用getInputStream()方法和getOutputStream()方法获得Socket对象的输入流和输出流4)服务器与客户端根据协议交互数据5)直至一端请求关闭连接,服务器和客户端连接终止6)服务器回到第2步,继续监听下一次的连接而客户端则运行结束import java.io.*;import .*;public class TcpServerstatic public void main(String args)try ServerSocket svrsoc=new ServerSocket(8000);Socke soc=svrsoc.accept();InputStream is=soc.getInputStream();/Socket输入流 DataInputStream in=new DataInputStream(is);OutputStream os=soc.getOutputStream();/Socket输出流 PrintStream out=new PrintStream(os);/*服务器创建输入流对象in和输出流对象out,接收客户输入信息(in)和向客户发送信息(out),同样,客户端也建立两个对象,与服务器双向通信。
服务器向输出流信息都成为客户输入信息,而客户输出的信息送入服务者的输入流/InetAddress clientIP=soc.getInetAddress();System.out.println(Clients IP address:+clientIP);int port=soc.getPort();/得到客户方的端口 System.out.println(Clients port:+port);out.println(Welcome!.);String str=in.readLine();/在输入流对象in中读一行 while(!str.equals(“quit”)System.out.println(“客户端:+str);str=in.readLine();System.out.println(“客户关机.);catch(Exception e)System.out.println(Error:+e);finally is.close();/关闭输入流 os.close();/关闭输出流 soc.close();/关闭socket,拆除链路 svrsoc.close();/关闭监听,停止服务 1、创建指定端口的ServerSocket对象2、调用accept()方法监听端口连接请求3-1、Socket绑定客户IP地址和端口3-2、调用getInputStream()或getOutputStream()方法获得Socket对象的输入流和输出流4、服务器与客户端连接根据协议交互数据5、请求关闭连接,服务器和客户端连接终止6、停止该用户TCP连接服务服务器套接字程序Java SocketSocket Socket创建一个客户端的典型工作流程:(1)创建一个指定地址和端口的Socket对象,建立服务器与客户端连接。
2)调用getInputStream()方法或getOutputStream()方法获得Socket对象的输入流和输出流3)服务器与客户端连接根据协议交互数据4)请求关闭连接,服务器和客户端连接终止import .*;import java.io.*;public class TcpClient static public void main(String args)try Socket soc=new Socket(localhost,8000);System.out.println(Connecting to the Server.);InputStream is =soc.getInputStream();OutputStream os =soc.getOutputStream();DataInputStream in=new DataInputStream(is);PrintStream out =new PrintStream(os);String strin =in.readLine();System.out.println(“服务器端:+strin);byte bmsg=new byte20;System.in.read(bmsg);String msg=new String(bmsg,0);msg=msg.trim();while(!msg.equals(quit)/从键盘循环读入,直到输入”quit”为止 out.println(msg);System.in.read(bmsg);msg=new String(bmsg,0);msg=msg.trim();out.println(msg);catch(Exception e)System.out.println(Error:+e);finally is.close();/关闭输入流 os.close();/关闭输出流 soc.close();/关闭socket,拆除链路 System.exit(0);1、创建指定地址和端口的Socket对象建立服务器与客户端连接2、调用getInputStream()或getOutputStream()方法获得Socket对象的输入流和输出流3、服务器与客户端连接根据协议交互数据4、关闭请求连接,服务器和客户端连接终止客户机套接字程序Socke通信编程-异常处理 ServerSocket和和socket编程需要进行编程需要进行try-catch异常处理异常处理(1)服务器端:)服务器端:ServerSocket server;Socket socket;try server=new ServerSocket(port);socket=server.accept();.catch(Exception e)System.out.println(“Error occurred:”+e);(2)客户端)客户端:Socket socket;try socket=new Socket(“Server Name”,port);catch(Exception e)System.out.println(“Error occurred:”+e);建立Socket连接后,利用方法getOutputStream()和getInputStream()建立向Socket读写数据的I/O流。
需要进行try-catch异常处理tryInputStream ins=socket.getInputStream();OutputStream outs=socket.getOutputStream();catch(Exception e)System.out.println(“Error occurred:”+e);Socke通信编程 建立/输出流 获取Socket的输入/输出流后,需要对两个流对象建立数据流的读/写操作InputStream ins=socket.getInputStream();OutputStream outs=socket.getOutputStream();或 PrintStream out=new PrintStream(outs);读入一个字符串并将其长度写入输出流中,则用:String str=inn.readLine();out.println(str.length();Socke通信编程 读写数据流 无论是服务器程序还是客户端程序,通信结束时,必须断开连接并释放所占用的资源Java断开连接方法:close();(1)关闭输入输出流 停止数据传输 (2)关闭socket 终止申请服务(3)关闭server socket 关闭监听服务Socke通信编程 释放连接问题:问题:Socket Socket设计输入流和输出流的处理,客户机与设计输入流和输出流的处理,客户机与服务器进行数据读取时将引起堵塞。
服务器进行数据读取时将引起堵塞解决办法:解决办法:服务器一旦接受到用户的服务器一旦接受到用户的SocketSocket,将专门为该,将专门为该用户建立在一个独立的线程,进行数据的访问交换用户建立在一个独立的线程,进行数据的访问交换操作/(2)服务器端程序import java.io.*;import .*;import java.util.*;public class Server public static void main(String args)ServerSocket server=null;ServerThread thread;Socket you=null;while(true)try server=new ServerSocket(4331);catch(IOException e1)System.out.println(“正在监听”);/ServerSocket对象不能重复创建try you=server.accept();System.out.println(客户的地址:+you.getInetAddress();catch(IOException e)System.out.println(正在等待客户);if(you!=null)new ServerThread(you).start();/为每个客户启动一个专门的线程。
else continue;class ServerThread extends Thread Socket socket;DataOutputStream out=null;DataInputStream in=null;String s=null;ServerThread(Socket t)socket=t;try in=new DataInputStream(socket.getInputStream();out=new DataOutputStream(socket.getOutputStream();catch(IOException e)public void run()while(true)double a=0,b=0,c=0,root1=0,root2=0;try a=in.readDouble();/堵塞状态,除非读取到信息b=in.readDouble();c=in.readDouble();double disk=b*b-4*a*c;root1=(-b+Math.sqrt(disk)/(2*a);root2=(-b-Math.sqrt(disk)/(2*a);out.writeDouble(root1);out.writeDouble(root2);catch(IOException e)System.out.println(客户离开);break;/(1)客户端程序import .*;import java.io.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;class Client extends JFrame implements Runnable,ActionListener JButton connection,computer;JTextField inputA,inputB,inputC;JTextArea showResult;Socket socket=null;DataInputStream in=null;DataOutputStream out=null;Thread thread;public Client()socket=new Socket();/待连接的套接字。
connection=new JButton(连接服务器);computer=new JButton(求方程的根);computer.setEnabled(false);/没有和服务器连接之前,该按钮不可用inputA=new JTextField(0,12);inputB=new JTextField(0,12);inputC=new JTextField(0,12);Box boxV1=Box.createVerticalBox();boxV1.add(new JLabel(输入2次项系数);boxV1.add(new JLabel(输入1次项系数);boxV1.add(new JLabel(输入常数项);Box boxV2=Box.createVerticalBox();boxV2.add(inputA);boxV2.add(inputB);boxV2.add(inputC);Box baseBox=Box.createHorizontalBox();baseBox.add(boxV1);baseBox.add(boxV2);Container con=getContentPane();con.setLayout(new FlowLayout();showResult=new JTextArea(8,18);con.add(connection);con.add(baseBox);con.add(computer);con.add(new JScrollPane(showResult);computer.addActionListener(this);connection.addActionListener(this);thread=new Thread(this);setBounds(100,100,360,310);setVisible(true);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);public void run()while(true)try double root1=in.readDouble();/堵塞状态,除非读取到信息。
double root2=in.readDouble();showResult.append(n两个根:n+root1+n+root2);showResult.setCaretPosition(showResult.getText().length();catch(IOException e)showResult.setText(与服务器已断开);computer.setEnabled(false);break;public void actionPerformed(ActionEvent e)if(e.getSource()=connection)try /请求和服务器建立套接字连接 if(socket.isConnected()else InetAddress address=InetAddress.getByName(127.0.0.1);InetSocketAddress socketAddress=new InetSocketAddress(address,4331);socket.connect(socketAddress);in=new DataInputStream(socket.getInputStream();out=new DataOutputStream(socket.getOutputStream();computer.setEnabled(true);thread.start();catch(IOException ee)if(e.getSource()=computer)try double a=Double.parseDouble(inputA.getText(),b=Double.parseDouble(inputB.getText(),c=Double.parseDouble(inputC.getText();double disk=b*b-4*a*c;if(disk=0)out.writeDouble(a);out.writeDouble(b);out.writeDouble(c);else inputA.setText(此2次方程无实根);catch(Exception ee)inputA.setText(请输入数字字符);public static void main(String args)Client win=new Client();2.3 项目实战:聊天室系统的设计与实现ServerClient n.Client 1A serve socketon a portA socket for aclientA socket for aclient1.系统整体框架(C/S模式)2.模块设计客户端登陆修改用户名发送聊天信息接收并显示聊天信息修改服务器地址服务器端启动服务器发送系统消息发送聊天信息接收并显示或转发聊天信息端口设置图图1 客户端模块设计客户端模块设计图图2 服务器端模块设计服务器端模块设计注册3.传送消息的种类及格式设计注册信息注册信息 0登陆信息登陆信息 1聊天信息聊天信息 2系统信息系统信息 3退出信息退出信息 4界面示意图1.类类 JComboBox 将按钮或可编辑字段与下拉列表组合的组件。
将按钮或可编辑字段与下拉列表组合的组件用户可以从下拉列表中选择值,下拉列表在用户可以从下拉列表中选择值,下拉列表在用户请求时显示如果使组合框处于可编辑用户请求时显示如果使组合框处于可编辑状态,则组合框将包括用户可在其中键入值状态,则组合框将包括用户可在其中键入值的可编辑字段的可编辑字段JComboBox(Object items)创建包含指创建包含指定数组中的元素的定数组中的元素的 JComboBox4.所需要的知识2.类类 ObjectInputStream和和ObjectOutputStream 可以读取可以读取/输出(重构)对象通过使用流中的文件可以输出(重构)对象通过使用流中的文件可以实现对象的持久存储如果流是网络套接字流,则可以实现对象的持久存储如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象在另一台主机上或另一个进程中重构对象nprotected ObjectOutputStream()为完全重新实现为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不的子类提供一种方法,让它不必分配仅由必分配仅由 ObjectOutputStream 的实现使用的私有的实现使用的私有数据。
数据nObjectOutputStream(OutputStream out)创建写创建写入指定入指定 OutputStream 的的ObjectOutputStream3.类类JDialog 创建对话框窗口的主要类可以使用此类创创建对话框窗口的主要类可以使用此类创建自定义的对话框,或者调用建自定义的对话框,或者调用 JOptionPane中的多个类方法来创建各种标中的多个类方法来创建各种标准对话框准对话框4.线程的创建线程的创建1)通过扩展)通过扩展Thread类类2)实现)实现Runnable接口接口5.结构体的设计结构体的设计 public class Node String username=null;Socket socket=null;ObjectOutputStream out=null;ObjectInputStream in=null;The end!聊天室系统的设计与实现聊天室系统的设计与实现1.聊天界面设计聊天界面设计2.客户端发送聊天消息,服务器端接受聊客户端发送聊天消息,服务器端接受聊天消息天消息3.服务器端发送聊天消息,客户端接受聊服务器端发送聊天消息,客户端接受聊天消息天消息4.合法性判断合法性判断5.启动服务,停止服务,退出启动服务,停止服务,退出6.连接设置连接设置7.多个客户端之间通信多个客户端之间通信8.数据库设计,注册及登陆数据库设计,注册及登陆计算机应用技术课程实习实习手册书写要求:实习手册书写要求:时间:时间:2011.1.4-1.15,共,共10次日志和次日志和2篇篇周记,周记,1篇实习报告篇实习报告第一周:第一周:4,5,6,7,8第二周:第二周:10,11,12,13,14上交形式:上交形式:纸质版和电子版纸质版和电子版。