我的历史遗留问题。关于JAVA的SOCKET

airwing 2000-12-19 11:00:00
我的部分代码:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.Socket;

private static Socket dataSocket;
private static DataInputStream socketDataIn;
private static DataOutputStream socketDataOut;

dataSocket = new Socket("172.16.18.1",1888);
dataSocket.setSoTimeout(5000);
dataSocket.setReceiveBufferSize(8192); //这个好象没起作用
socketDataIn = new DataInputStream(dataSocket.getInputStream());
socketDataOut= new DataOutputStream(dataSocket.getOutputStream());

socketDataOut.write(outDataBuff,0,2049);//大于2048的部分收不到
...
int pLength = socketDataIn.read(inDataBuff);

-------------------------------------------------------------------------

我的问题就是当发送超过2048个字节时,SOCKET另外一端收不全,必须再read一次。而我认为这个机制应该是由TCP层提供的,其他的工具C(UNIX)和DELHPI(WINDOWS)均无此问题。难道是JAVA的?

欢迎大家来讨论!
...全文
251 点赞 收藏 11
写回复
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
kz 2000-12-22
to airwing
是这样,例如TCP层发送数据513个字节,但你的网卡与下一个节点如中继器的通信有一个最小发送单位--比方512个字节。当TCP层flush()时物理层即网卡发送了两个数据包:一个512个字节;另一个也是512个字节(但只包含一个有用数据。当从另一端接收时,第一次read将512个字节放入了你的缓冲区(注意:接收必须是以数据包为单位),所以你必须再read一次
回复
Mars_lee 2000-12-21
关注关注,我也想知道怎么回事,提一提
我也帮你问一问
回复
airwing 2000-12-20
拉一拉,敬请关注
回复
airwing 2000-12-20
to kz
和物理层无关,任何应用层数据都会在IP层被分割层多个IP包,由TCP层负责传输和顺序、差错控制。难道各位做程序都只发512字节吗?
回复
kz 2000-12-20
to airwing
我还是觉得与底层有关,因为setReceiveBuffer只是告诉JAVA系统设定一种缓冲机制
但数据总是要发送到网络上的。在物理层,存在一个最小发送长度,如通过ATM传送时好象是512个字节,你可以看看有关书籍,自然明白底层的运作
回复
airwing 2000-12-19
这部分的原因应该是如borz所说,与流的限制有关。与JAVA的SOCKET机制无关。
发送是0x1001个字节
接收是0x1002个字节

那么大家继续讨论,在这种情况下,难道要我们自己来做底层的工作吗?大家有什么好办法
回复
borz 2000-12-19
DATAOUTPUTSTREM 之类的是发送UNICODE,所以。。。。
回复
Mars_lee 2000-12-19
是不是这里啊?

dataSocket.setSendBufferSize(8192);

或者是catch一下io的exception.........

回复
airwing 2000-12-19
我的问题出在socket的in上,是read读不到完整的包。这里的包长度是指我们在应用层上的定义,跟底层的无关。底层会帮我们实现差错控制。
回复
kz 2000-12-19
socketDataOut.flush();
底层发送都存在一个最小尺度问题,如512字节满了才自动发送,而你的代码刚好不够,所以不会引发自动发送
回复
airwing 2000-12-19
错了!是在SOCKET的socketOptions里 /**
* Set a hint the size of the underlying buffers used by the
* platform for outgoing network I/O. When used in set, this is a
* suggestion to the kernel from the application about the size of
* buffers to use for the data to be sent over the socket. When
* used in get, this must return the size of the buffer actually
* used by the platform when sending out data on this socket.
*
* Valid for all sockets: SocketImpl, DatagramSocketImpl
*
* @see Socket#setSendBufferSize
* @see Socket#getSendBufferSize
* @see DatagramSocket#setSendBufferSize
* @see DatagramSocket#getSendBufferSize
*/
public final static int SO_SNDBUF = 0x1001;

/**
* Set a hint the size of the underlying buffers used by the
* platform for incoming network I/O. When used in set, this is a
* suggestion to the kernel from the application about the size of
* buffers to use for the data to be received over the
* socket. When used in get, this must return the size of the
* buffer actually used by the platform when receiving in data on
* this socket.
*
* Valid for all sockets: SocketImpl, DatagramSocketImpl
*
* @see Socket#setReceiveBufferSize
* @see Socket#getReceiveBufferSize
* @see DatagramSocket#setReceiveBufferSize
* @see DatagramSocket#getReceiveBufferSize
*/
public final static int SO_RCVBUF = 0x1002;

回复
发动态
发帖子
Java SE
创建于2007-09-28

6.1w+

社区成员

Java 2 Standard Edition
申请成为版主
社区公告
暂无公告