Java Socket网络编程
1. TCP流式Socket
TCP是TCP/IP体系结构中位于传输层的面向连接的协议,提供可靠的字节流传输。通信双方需要建立连接,发送端的所有数据按顺序发送,接受端按顺序接收。
Java提供了ServerSocket类和Socket类用于基于TCP流式Socket的网络通信。ServerSocket类用于服务器,监听来自客户机的连接请求。Socket类用于客户机及服务器,建立客户机和服务器的连接。客户机与服务器建立起连接后,就可以基于此连接进行流式通信。
2. 服务器程序
(1)监听请求
在服务器程序中建立ServerSocket类对象,在某一端口监听来自客户机的连接请求。ServerSocket类的构造方法如下:
public ServerSocket(int port)
其中,int类型的port表示监听请求的端口号。
创建ServerSocket类对象时,可能触发IOException异常,在程序中需要进行抛出或捕获处理。
(2)捕获请求
在服务器程序中调用ServerSocket类的的accept()方法,捕获客户机的连接请求。方法使服务器程序处于阻塞状态,直到捕获到来自某一客户机的连接请求。当捕获到来
自某客户机通过其Socket 类对象发送来的连接请求时,accept()方法返回(创建)与
请求对应的Socket类对象,建立起与客户机的连接。
当在服务器创建了Socket 类对象后,就可以通过该类对象与所连接的客户机进行流
式通信。
accept()方法的声明如下:public Socket accept();
为了让服务器在500号端口监听连接请求,并当捕获到客户机的连线请求时,创建对位的Socket类对象ssocket.建立起与客户机的连接,可以使用以下动句序到:
ServerSocket server1=new ServerSocket (5000);
Socket ssocket=server1. accept()
(3)流式通信
Socket类提供了getInputStream()方法和getOutputStream()方法, 生成对应的InputStream类对象和OutputStream类对象。通过InputStream类对象从所连接的客户机获取信息,通过OutputStream类对象向所连接的客户机发送信息。
创建Socket类对象时,可能触发IOExeption类异常,在程序中需要进行物出或捕获处理。
为了便于输人(获取)和输出(发送)信息,可以在生成的InputStream和OutputStream基础上,创建DataInputStream 、DataOutpuStraem或PintStream等类对象;对于
文本流通信,可以创建InputStreamReader、OutputStreamReader或PrintWriter
等类对象进行通信处理。
例如,为Socket类对象socket建立DataInputStream类对象is和PrintStream 类对象ps,可以使用以下语句序列:
DataInputStream is=new DataInputStream (ssocket.getInputstream());
PrintStream ps=new PrintStream( new BufferedOutputStream(ssocket.getOutputStream());
(4)结束通信
通信任务完成后,应该将Socket 类对象关闭,切断与客户机的连接,并关闭对应的流对象,以释放所占资源。
关闭Socket类对象要使用Socket类的close()方法。close()方法声明如下:
public void close () ;
注意:先关闭流对象,后再关闭Socket类对象。
3. 客户机程序
客户机程序的流程如下:
( 1)建立连接
在客户机程序中创建Sockel类对象,向指定服务器的某端口 发送连接请求。Socket类的构造方法如下:
public Socket (InetAddress addr,int port) ;
public Socket(String host,int port) ;
其中,addr 表示服务器的InetAddress类对象,host 表示服务器的域名或IP地址,port表示服务器端口号。
创建Socket 类对象时,可能触发I0Exception 类异常,在程序中需要进行抛出或捕获处理。
当在客户机创建了Socket 类对象,与指定的服务器建立起连接后,就可以通过该类对象与所连接的服务器进行流式通信。
例如,百度Web服务器的域名为www.baidu.com, IP地址为119.75.217.109。 客户机向该服务器80号端口发送连接请求,建立Socket类对象soc,可以采用以下两条语句中
的任一条:
Socket soc=new Socket ("www. baidu. com",80) ;
Socket soc=new Socket ("119.75.217.109",80);
(2)流式通信
调用Socket 类对象的getlnputStream( )方法和getOutputream( )方法,生成对应的InputStream类对象和OutputStream类对象。通过InputStream类对象从所连接的服务器获取信息,通过OutputStream类对象向所连接的服务器发送信息。
(3) 结束通信
通信任务完成后,应该将Socket类对象关闭,切断与服务器的连接,并关闭对应的流对象,以释放所占资源。
4.多线程实现双机通信
package chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class Client { public static void main(String[] args) { Socket csocket=null; BufferedReader csockIn; PrintWriter csockOut; try { csocket=new Socket("127.0.0.1",8800); ClientThreadReceive ctr=new ClientThreadReceive(csocket); Thread thC=new Thread(ctr); thC.start(); ClientThreadSend ctS=new ClientThreadSend(csocket); Thread thS=new Thread(ctS); thS.start(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
package chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class ClientThreadReceive implements Runnable{ Socket csocket=null; BufferedReader csockIn; public ClientThreadReceive(Socket csocket) throws IOException { super(); this.csocket = csocket; csockIn=new BufferedReader(new InputStreamReader(csocket.getInputStream())); } @Override public void run() { while(true){ String s; try { s = csockIn.readLine(); System.out.println("client receiving:"+s); } catch (IOException e) { e.printStackTrace(); } } } }
package chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class ClientThreadSend implements Runnable{ Socket csocket=null; PrintWriter csockOut=null; BufferedReader input=new BufferedReader(new InputStreamReader(System.in)); public ClientThreadSend(Socket csocket) throws IOException { super(); this.csocket = csocket; csockOut=new PrintWriter(csocket.getOutputStream()); } @Override public void run() { while(true){ String s3; try { s3 = input.readLine();//从键盘读取一行信息 csockOut.println(s3); csockOut.flush(); } catch (IOException e) { e.printStackTrace(); } } }
package chat;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket=null; Socket ssocket=null; BufferedReader ssockIn; PrintWriter ssockOut; serverSocket=new ServerSocket(8800); System.out.println("等待客户端连接"); ssocket=serverSocket.accept();//会阻塞 ServerThreadReceive threadR=new ServerThreadReceive(ssocket); Thread thread=new Thread(threadR); thread.start();
ServerThreadSend threadS=new ServerThreadSend(ssocket); Thread thread2=new Thread(threadS); thread2.start(); } }
package chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class ServerThreadReceive implements Runnable{ Socket ssocket; BufferedReader ssockIn=null; public ServerThreadReceive(Socket ssocket) throws IOException { super(); this.ssocket = ssocket; ssockIn=new BufferedReader(new InputStreamReader(ssocket.getInputStream())); } @Override public void run() { while(true){ String s = null; try { s = ssockIn.readLine(); System.out.println("server receivging:"+s); } catch (IOException e) { e.printStackTrace(); } } } }
package chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class ServerThreadSend implements Runnable{ Socket ssocket; PrintWriter ssockOut; BufferedReader input=new BufferedReader(new InputStreamReader(System.in)); public ServerThreadSend(Socket ssocket) throws IOException { super(); this.ssocket = ssocket; ssockOut=new PrintWriter(ssocket.getOutputStream()); } @Override public void run() { while(true){ try { String s3=input.readLine(); ssockOut.println(s3); ssockOut.flush(); } catch (IOException e) { e.printStackTrace(); } } } }