网络编程的基本模型就是客户机到服务器模型,简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置。并去建立两者之间的联系,然后完成数据的通讯就可以了,这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端,基于这个简单的模型,就可以进入网络编程啦。
Java对这个模型的支持有很多种Api,而这里我只想介绍有关Socket的编程接口,对于Java而言已经简化了Socket的编程接口。首先我们来讨论有关提供固定位置的服务方是如何建立的。Java提供了ServerSocket来对其进行支持.事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你,ServerSocket server=new ServerSocket(6789);这里稍微要注意的是端口的分配必须是唯一的。因为端口是为了唯一标识每台计算机唯一服务的,另外端口号是从0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的。好了,我们有了固定位置.现在所需要的就是一根连接线了.该连接线由客户方首先提出要求。因此Java同样提供了一个Socket对象来对其进行支持,只要客户方创建一个Socket的实例对象进行支持就可以了。Socket client
=new Socket(InetAddress.getLocalHost(),5678);客户机必须知道有关服务器的IP地址,对于着一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供,它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法。
上面的方法基本可以建立一条连线让两台计算机相互交流了,可是数据是如何传输的呢?事实上I/O操作总是和网络编程息息相关的。因为底层的网络是继续数据的,除非远程调用,处理问题的核心在执行上,否则数据的交互还是依赖于IO操作的,所以你也必须导入java.io这个包.java的IO操作也不复杂,它提供了针对于字节流和Unicode的读者和写者,然后也提供了一个缓冲用于数据的读写。
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
上面两句就是建立缓冲并把原始的字节流转变为Unicode可以操作,而原始的字节流来源于Socket的两个方法,getInputStream()和getOutputStream()方,分别用来得到输入和输出,那么现在有了基本的模型和基本的操作工具,我们可以做一个简单的Socket例程了.
该实例完成的功能如下:
一次启动Server端和Client端后,首先由Server端发‘1’给Client端,Client端将接收到的数据加1后,发该数据给Server端,Server端再将数据加1后发给Client端,依次类推。直到Server端收到数据20,Client收到19时,两方中断收发。
程序代码如下:
- Socket Server
* Socket的Server举例
* @author Amigo Xie(xiexingxing1121@126.com)
* @since 2006/12/28
*/
public class SocketServer {
ServerSocket serverSocket = null;
Socket socket = null;
DataInputStream inStream = null;
DataOutputStream outStream = null;
public static void main(String[] args) {
SocketServer socketServer = new SocketServer();
socketServer.waitForClient();
}
public SocketServer() {
try {
serverSocket = new ServerSocket(6600);
} catch(Exception e) {
e.printStackTrace();
}
}
void waitForClient() {
try {
socket = serverSocket.accept();
inStream = new DataInputStream(socket.getInputStream());
outStream = new DataOutputStream(socket.getOutputStream());
outStream.writeUTF("1");
socket.setSoTimeout(3000);
acceptAndSendData();
} catch(Exception e) {
e.printStackTrace();
}
}
void acceptAndSendData(){
while(true) {
try {
String acceptStr = inStream.readUTF();
System.out.println("Server accept:" + acceptStr);
int num = Integer.parseInt(acceptStr) + 1;
if(num > 20) {
System.out.println("Send end!");
break;
} else {
String sendStr = Integer.toString(num);
outStream.writeUTF(sendStr);
}
} catch(Exception e) {
e.printStackTrace();
break;
}
}
}
}
2. Socket Client端代码
* Socket的Client举例
* @author Amigo Xie(xiexingxing1121@126.com)
* @since 2006/12/28
*/
public class SocketCliet {
Socket socket = null;
DataInputStream inStream = null;
DataOutputStream outStream = null;
public static void main(String[] args) {
SocketCliet socketCliet = new SocketCliet();
}
public SocketCliet() {
try {
init();
waitData();
} catch (Exception e) {
e.printStackTrace();
}
}
void init() throws Exception {
socket = new Socket("127.0.0.1", 6600);
inStream = new DataInputStream(socket.getInputStream());
outStream = new DataOutputStream(socket.getOutputStream());
socket.setSoTimeout(3000);
}
void waitData() {
boolean flag = true;
while (flag) {
try {
String acceptStr = inStream.readUTF();
System.out.println("Client accept: " + acceptStr);
String sendStr = Integer.toString(Integer.parseInt(acceptStr) + 1);
outStream.writeUTF(sendStr);
if(Integer.parseInt(sendStr) >= 20) {
flag = false;
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
}