`
liyixing1
  • 浏览: 961622 次
  • 性别: Icon_minigender_1
  • 来自: 江西上饶
社区版块
存档分类
最新评论
阅读更多
在基础网络协议上,java 支持TCP/IP 和UDP/IP。在网络操作上java支持BIO和NIO(新I/O可以查看http://tech.ccidnet.com/art/322/20030903/62354_1.html)。因此java拥有四种方法实现基于消息的系统间通讯。

1.TCP/IP+BIO
java对于TCP/IP方式的网络传输提供了socket机制,这也是传统unix网络通讯的抽象机制。
而TCP/IP+BIO方式,java提供了Socket和ServerSocket两个关键类来实现。网络操作是通过java中的流对象进行的。包括:
服务端:
new ServerSocket(int port)端口(unix中1024以下端口需要root权限开启)
Socket socket = serverSocket.accept()
socket.getInputStream();
socket.getOutputStream();

客户端则是:
new Socket(String host, int port);建立连接,如果服务器未启动,则会报出Connection refused异常。
socket.getInputStream();
socket.getOutputstream();

下面给出一个完整的TCP/IP+BIO方式的
Client

package client;

import java.io.*;

import java.net.Socket;

import java.net.UnknownHostException;

public class Client {

static int RMIPort = 9999;

public static void main(String[] args) throws ClassNotFoundException {

try {

Socket socket = new Socket("127.0.0.1", 9999);
byte[] bytes = new byte[64];

while (true) {

InputStream serverinput = socket.getInputStream();
int length = serverinput.read(bytes);
if (length > 0) {
System.out.println(new String(bytes, 0, length));
}
}

} catch (UnknownHostException e) {
e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}
}

Server

package server;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
public static void main(String[] args) {

System.out.println("开始侦听请求 。。。。");

ServerSocket serverSocket;

try {

serverSocket = new ServerSocket(9999);

// 服务器套接字

Socket clientSocket = null;

clientSocket = serverSocket.accept();// 获得客户端的请求的Socket

System.out.println("已侦听到了客户端的请求。。。。。");

OutputStream os = clientSocket.getOutputStream();

while (true) {
os.write("test".getBytes());
os.write("a".getBytes());
os.write("b".getBytes());
os.write("c".getBytes());
os.flush();
//os.flush();
}

} catch (IOException e) {
e.printStackTrace();
}

}

}

我对上面的代码进行过debug
1.对客户端的read方法的测试
如果我把服务端断点设置os.write("test".getBytes());客户端断点设在int length = serverinput.read(bytes);
如图






此时在debug中可以看到Server.main和Client.main线程,我进入Client线程
int length = serverinput.read(bytes);
让这句执行下去,发现Client处于等待状态。



然后我进入Server线程
让os.write("test".getBytes());执行下去。
发现Client被激活了


可以确定一点read方法如果服务端无数据过来,它会让整个线程进入等待状态,直到有数据过来。

然后我让Client一直执行下去,直到while下次循环开始,到int length = serverinput.read(bytes);这句又让被断点停住。
然后我回到Server,让Servlet到os.write("c".getBytes());被断点停住。
,然后回到Client,让Client执行下去。发现Client同时把ab两个字符都读出来了。说明read读取的数量不是服务端一次write的数量。而是从字节流缓存器读一次。一个缓冲器的数据就是最终读取的数据量。


上图是Client的输出结果

下面是对read的长度的测试;
由于很多情况下我们都是对read的结果来进行判断数据读取时候结束的。当返回的长度<1我们就认为是读取结束了。代码可能类似我上面的Client中的
int length = serverinput.read(bytes);
if (length > 0) {
System.out.println(new String(bytes, 0, length));
}
那么read在什么情况下会返回< 1的结果呢?

我修改Server,

package server;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
public static void main(String[] args) {

System.out.println("开始侦听请求 。。。。");

ServerSocket serverSocket;

try {

serverSocket = new ServerSocket(9999);

// 服务器套接字

Socket clientSocket = null;

clientSocket = serverSocket.accept();// 获得客户端的请求的Socket

System.out.println("已侦听到了客户端的请求。。。。。");

OutputStream os = clientSocket.getOutputStream();

os.close();

} catch (IOException e) {
e.printStackTrace();
}

}

}

注意上面,客户端链接过来后,服务端会把输出流关闭。
客户端断点还是设在int length = serverinput.read(bytes);
服务端断点设置在
os.close();

然后我测试了下
让客户端int length = serverinput.read(bytes);这句执行下去
这时候客户端线程已经暂停了。
然后让服务端的os.close();这句执行下去。
发现客户端被激活了。
但是可以看到这时候客户端的length值是-1



可见read为-1的情况是连接断开或其他原因,造成两边无法传递数据的情况下。

由于我没有看过TCP/IP协议的完整资料。所以以上只是个人测试的结果,我无法提供TCP/IP的资料加以确认。
  • 大小: 7 KB
  • 大小: 7.3 KB
  • 大小: 20.1 KB
  • 大小: 6.2 KB
  • 大小: 8.8 KB
  • 大小: 1 KB
  • 大小: 5.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics