java.net包中包含流套接字:服务器端Socket使用ServerSocket类,客户端Socket使用Socket类。
Socket类的输入输出都是通过流来实现的。通过主机操作系统直接使用本地TCP栈进行通信。客户端流Socket的创建可通过使用Socket类的构造函数完成。构造函数不仅可以创建Socket对象,并且会尝试连接服务器端的Socket。可通过构造方法测试某个端口的连接是否允许。
ServerSocket类用在服务器端,侦听和响应客户端的连接请求,并接收客户端发送的数据。具体功能:服务器启动,耐心地等候客户端的连接请求,一旦客户端应用程序申请建立一个Socket连接,Server Socket类就会通过accept()方法返回一个对应的服务器端Socket对象,以便进行直接通信。从两台计算机连接成功时起,服务器端与客户端就得到了一个真正的“Socket-Socket”连接。 5、Socket编程的基本步骤:
1.服务器端应用程序编写步骤(1)创建一个等待连接的ServerSocket对象,如Sersocket;(2)调用Sersocket对象的accept()方法侦听接收客户端的连接请求。当侦听到一个客户的连接请求时,连接成功,并返回一个用于通信的Socket对象;(3)创建与Socket对象绑定的输入输出流,并建立相应的数据输入输出流;(4)通过数据输入输出流与客户端进行数据读写,完成双向通信;(5)当客户端断开连接时,关闭各个流对象,结束通信。(2)~(5)可循环执行。
2.客户端应用程序编写步骤(1)创建指定服务器上指定端口号的Socket对象;(2)创建与Socket对象绑定的输入输出流,并建立相应的数据输入输出流;(3)通过数据输入输出流与服务器端进行数据读写,完成双向通信;(4)通过调用close()方法关闭与服务器端的连接,并关闭各个流对象,结束通信。
6、UDP编程:用户数据报协议(User Datagram Protocol,UDP)是一种面向无连接的传输层协议,提供简单的不可靠数据传送服务。 特点:传输数据之前客户端和服务器端不建立连接,当它想发送数据时则获取来自应用程序的数据,并尽可能快地把它放到网络上。由于传输数据时不需建立连接,不需维护连接状态,因此一台服务器可同时向多个客户传输相同的数据。
UDP使用的类:DatagramPacket类包含具体的要传输的信息,这些信息被封装在称为数据报(Datagram)的UDP包中
DatagramSocket类用于收发UDP数据报。工作原理:发送数据时:需将数据封装到DatagramPacket中,使用DatagramSocket发送该包。接收数据时要从DatagramSocket中接收一个DatagramPakcet对象,然后解析该包的内容。
DatagramPacket类:定义:该类表示一个数据报包。该数据报包用来实现一个无连接包的传送服务。它是进行数据报通信的基本单位。包含了IP地址、端口号和需要传输的数据等。在发送和接收数据报时,要创建DatagramPakcet类对象作为数据的载体。
DatagramSocket类:该类表示用来发送和接收数据报包的套接字(Socket)要收发DatagramPacket,必须打开一个数据报套接字(Datagram Socket)。在Java中,数据报套接字通过DatagramSocket类来创建和访问。
7、基于UDP协议的Socket编程:建立一个DatagramSocket对象;创建用于接收或发送数据的DatagramPacket对象;利用DatagramSocket类方法receive()或send()接收或发送数据报包。
1.服务器端程序具体开发步骤:1)建立一个DatagramSocket对象;(2)进入收发数据报包的循环,直到客户端数据传送完毕。循环过程如下:创建一个用于接收数据的DatagramPakcet对象;利用DatagramSocket的receive()等待接收数据报包;处理客户端数据报包内容;创建一个用于发送响应信息数据的DatagramPakcet对象,利用DatagramSocket类方法send()向客户端发送包含响应信息的数据报包;(3)客户端数据传送完毕,释放Socket。 2.客户端程序具体开发步骤:1)建立一个DatagramSocket对象;(2)进入发收数据报包的循环,直到数据传送完毕。循环过程如下:创建一个用于发送数据的DatagramPakcet对象,并将要发送的数据封装到该数据报包;利用DatagramSocket类send()向服务器端发送数据报包;创建一个用于接收响应信息数据的DatagramPakcet对象;利用DatagramSocket类方法receive()等待接收服务器端包含响应信息的数据报包;处理服务器端数据报包内容。(3)
数据传送完毕,释放Socket。
8、UDP与TCP的比较:UDP没有两台主机间唯一连接的概念。使用UDP时,每个数据报中都给出了完整的地址信息,因此无需要建立连接。对于TCP协议,在Socket之间进行数据传输之前必然要建立连接。一个DatagramSocket可以从多个独立主机接收数据,也可向多个主机传输相同的数据,此Socket并不专用于一个连接。传输方式:TCP Socket将网络视为流,通过与Socket相关的输入输出流来收发数据。流中的数据是有序的,而UDP所处理的总是单个数据报包封装在一个数据报中的数据都以一个包的形式整体收发,一个包不需与其它包相关,各数据报包之间是无序的。数据量限制:使用UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。TCP没有这方面的限制。 9、例子 TCP:
public class ClientTest {
public static void main(String args[]) { new ComputerClient(); } }
class ComputerClient extends Frame implements Runnable,ActionListener { Button connection,send;
TextField inputText,showResult; Socket socket=null;
DataInputStream in=null; DataOutputStream out=null; Thread thread; ComputerClient()
{ socket=new Socket();
setLayout(new FlowLayout()); Box box=Box.createVerticalBox();
connection=new Button(\连接服务器\ send=new Button(\发送\ send.setEnabled(false);
inputText=new TextField(12); showResult=new TextField(12); box.add(connection);
box.add(new Label(\输入三角形三边的长度,用逗号或空格分隔:\ box.add(inputText); box.add(send);
box.add(new Label(\收到的结果:\ box.add(showResult);
connection.addActionListener(this); send.addActionListener(this); thread=new Thread(this); add(box);
setBounds(10,30,300,400); setVisible(true); validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0); } }); }
public void actionPerformed(ActionEvent e) { if(e.getSource()==connection)
{ try //请求和服务器建立套接字连接: { if(socket.isConnected()) {} else
{ InetAddress address=InetAddress.getByName(\
InetSocketAddress socketAddress=new InetSocketAddress(address,4331); socket.connect(socketAddress);
in =new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream()); send.setEnabled(true); thread.start(); } }
catch (IOException ee){} }
if(e.getSource()==send) { String s=inputText.getText(); if(s!=null) { try { out.writeUTF(s); }
catch(IOException e1){} } } }
public void run() { String s=null; while(true) { try{ s=in.readUTF();
showResult.setText(s); }
catch(IOException e)
{ showResult.setText(\与服务器已断开\ break; } } } }
public class ServerTest {
public static void main(String args[]) { ServerSocket server=null; Server_thread thread; Socket you=null; while(true) { try{ server=new ServerSocket(4331); }
catch(IOException e1)
{ System.out.println(\正在监听\对象不能重复创建 }
try{ System.out.println(\等待客户呼叫\ you=server.accept();
System.out.println(\客户的地址:\ }
catch (IOException e)
{ System.out.println(\正在等待客户\ }
if(you!=null)
{ new Server_thread(you).start(); //为每个客户启动一个专门的线程 } } } }
class Server_thread extends Thread {
Socket socket;
DataOutputStream out=null; DataInputStream in=null; String s=null;
boolean quesion=false; Server_thread(Socket t) { socket=t; try { out=new DataOutputStream(socket.getOutputStream()); in=new DataInputStream(socket.getInputStream()); }
catch (IOException e)
{e.printStackTrace();} }
public void run() { while(true) { double a[]=new double[3] ; int i=0; try{ s=in.readUTF();//堵塞状态,除非读取到信息 quesion=false;
StringTokenizer fenxi=new StringTokenizer(s,\ while(fenxi.hasMoreTokens())
{ String temp=fenxi.nextToken(); try{ a[i]=Double.valueOf(temp).doubleValue(); i++; }
catch(NumberFormatException e) { out.writeUTF(\请输入数字字符\ quesion=true; } }
if(quesion==false) {
double p=(a[0]+a[1]+a[2])/2.0;
out.writeUTF(\ } }
catch (IOException e)
{ System.out.println(\客户离开\ return;
} } } }
UDP:
lass Beijing_Frame extends Frame implements Runnable,ActionListener { TextField out_message=new TextField(\发送数据到上海:\ TextArea in_message=new TextArea();
Button b=new Button(\发送数据包到上海\ Beijing_Frame()
{ super(\我是北京\
setSize(200,200);setVisible(true); b.addActionListener(this);
add(out_message,\ Thread thread=new Thread(this); thread.start();//线程负责接收数据包 }
public void actionPerformed(ActionEvent event)
{ byte buffer[]=out_message.getText().trim().getBytes();
try{ InetAddress address=InetAddress.getByName(\DatagramPacket data_pack=
new DatagramPacket(buffer,buffer.length, address,666);
DatagramSocket mail_data=new DatagramSocket();
in_message.append(\数据报目标主机地址:\ in_message.append(\数据报目标端口是:\ in_message.append(\数据报长度:\ mail_data.send(data_pack); }
catch(Exception e){} }
public void run()
{ DatagramSocket mail_data=null; byte data[]=new byte[8192]; DatagramPacket pack=null; try{
pack=new DatagramPacket(data,data.length); mail_data=new DatagramSocket(888); }
catch(Exception e){} while(true)
{ if(mail_data==null) break; else
try{ mail_data.receive(pack); int length=pack.getLength();
InetAddress adress=pack.getAddress(); int port=pack.getPort();
String message=new String(pack.getData(),0,length);
in_message.append(\收到数据长度:\
in_message.append(\收到数据来自:\端口:\ in_message.append(\收到数据是:\ }
catch(Exception e){} } } }

