example , there are two cases, case 1 : will not clog ; case 2 : will be blocked ;
code is as follows :
//客户端
public class CompressClient
{
public static final int BUFSIZE = 256;
public static void main(String[] args) throws IOException
{
InetAddress inetAddr = InetAddress.getLocalHost();
int port = 8888;
String fileName = "D:\\杂乱\\桌面.jpg";
FileOutputStream fileOut = new FileOutputStream(fileName + ".gz");
final FileInputStream fileIn = new FileInputStream(new File(fileName));
final Socket sock = new Socket(inetAddr, port);
// 情况一:不会出现阻塞
// Thread thread = new Thread()
// {
// @Override
// public void run()
// {
// try
// {
// sendBytes(sock, fileIn);
// }
// catch (IOException e)
// {
// e.printStackTrace();
// }
// }
// };
// thread.start();
// 情况二:会出现阻塞
sendBytes(sock, fileIn);
// 接收压缩服务器信息
InputStream sockIn = sock.getInputStream();
int bytesRead;
byte[] buffer = new byte[BUFSIZE];
while ((bytesRead = sockIn.read(buffer)) != -1)
{
fileOut.write(buffer, 0, bytesRead);
System.out.print("R");
}
System.out.println();
fileIn.close();
fileOut.close();
sock.close();
}
private static void sendBytes(Socket socket, InputStream fileIn)
throws IOException
{
OutputStream sockOut = socket.getOutputStream();
int bytesRead = 0;
byte[] buffer = new byte[BUFSIZE];
while ((bytesRead = fileIn.read(buffer)) != -1)
{
sockOut.write(buffer, 0, bytesRead);
System.out.print("W");
}
System.out.println("\nClient send data complete!");
socket.shutdownOutput();
System.out.println("Client is deadlock? No");
}
}
//服务端
public class TCPEchoServerExecutor
{
public static void main(String[] args) throws IOException
{
int echoServProt = 8888;
ServerSocket servSock = new ServerSocket(echoServProt);
Logger logger = Logger.getLogger("practical");
Executor service = Executors.newCachedThreadPool();
while (true)
{
Socket clntSock = servSock.accept();
service.execute(new CompressProtocol(clntSock, logger));
}
}
}
//线程任务类
public class CompressProtocol implements Runnable
{
public static final int BUFSIZE = 1024;
private Socket clntSock;
private Logger logger;
public CompressProtocol(Socket clntSock, Logger logger)
{
this.clntSock = clntSock;
this.logger = logger;
}
public static void handleCompressClient(Socket clntSock, Logger logger)
{
try
{
InputStream in = clntSock.getInputStream();
GZIPOutputStream out = new GZIPOutputStream(
clntSock.getOutputStream());
byte[] buffer = new byte[BUFSIZE];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, bytesRead);
}
out.finish();
logger.info("Server:" + clntSock.getRemoteSocketAddress()
+ " finished");
}
catch (IOException e)
{
logger.log(Level.WARNING, "Exception in echo protocol", e);
}
try
{
clntSock.close();
}
catch (IOException e)
{
logger.info("Exception = " + e.getMessage());
}
}
@Override
public void run()
{
handleCompressClient(clntSock, logger);
}
}
Two commented the situation , but the use of a code , it will not be blocked . This is what principle ah ? We can explain the explanation?
------ Solution ---------------------------------------- ----
private static void sendBytes (Socket socket, InputStream fileIn)
throws IOException
{
OutputStream sockOut = socket.getOutputStream ();
int bytesRead = 0;
byte [] buffer = new byte [BUFSIZE];
while ((bytesRead = fileIn.read (buffer))! = -1) / / Here will be blocked because if there is no bytes are read , then blocked
{
sockOut.write (buffer, 0, bytesRead);
System.out.print ("W");
}
System.out.println ("\ nClient send data complete!");
socket.shutdownOutput ();
System.out.println ("Client is deadlock No?");
}
The code in question ,
------ Solution ------------------------------ --------------
//不管是客户机,还是服务器程序,你这段代码只能是学习用, 要用到项目中去, 不能这么简单的写.
while ((bytesRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, bytesRead);
}
use the following code, and then improve their own :
try{
int pava=0;
int cava=0;
int sumb=0;
int i=0;
int c=0;
ByteArrayOutputStream buffeOut =new ByteArrayOutputStream();
byte readbuf[] = new byte[10240];
while (socket.isConnected() && !socket.isClosed()) {
i++;
pava =in.available();
if(pava>0){
while ((c = in.read(readbuf)) != -1) {
buffeOut.write(readbuf, 0, c);
sumb =sumb + c;
cava =in.available();
if(cava<=0){
Thread.sleep(100);
cava =in.available();
if(cava<=0) break;
}
}
String strin = new String(buffeOut.toByteArray(),"utf-8");
System.out.println("读取流数据内容: "+strin+","+sumb);
buffeOut.reset();
//读完后回复信息.
out.write((i+",我是服务器,已收到数据!").getBytes("utf-8"));
out.flush();
if(c == -1) break;//对方关闭了输入流.
}else{
sumb=0;
out.write((i+",我是服务器,请发送数据!").getBytes("utf-8"));
out.flush();
Thread.sleep(1000);
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Request,NO["+requestCount+"],读取流数据完成.");
}
------ For reference only ----------------------------------- ----
answer is no well-wishers it? Online ......
------ For reference only ---------------------------- -----------
right, I ask you to send queue and (RecvQ) receive queue size is how much ah TCP socket (SendQ) in ?
------ For reference only ---------------------------------------
read the socket read ! (buffer) = -1 only in one case established that in each call socket.shutdownOutput (); methods.
-1 otherwise never have occurred , so you never end here , unless two conditions:
1 each call socket.shutdownOutput () ;/ / You will receive a -1 , but if the other program is not what you write , can not guarantee oh.
2 each call socket.close (); / / there is an exception, the end , but when you have to re- write data anomalies appear
-----!! - For reference only ---------------------------------------
Thank you, my own problems to solve , first you will good, but one thing you analyze wrong, when calling sockOut.write (buffer, 0, bytesRead), I found that the program is here was only blocked , indicating that - " receiving end SendQ queue has been filled , so will cause obstruction when the server calls sockOut.write (buffer, 0, bytesRead)", this problems with "Socket receive queue SendQ" about !
However, there still want to thank you , while ((bytesRead = in.read (buffer))! = -1) is used in this way depends on what the scene , You can also use the " custom message boundary character " to achieve .
Thank you !
------ For reference only -------------------------------------- -
"! socket in the read (buffer) = -1 only established in one case ," you say this view is wrong , the correct view is : Only two views establishment , 1.socket.shutdownOutput () 2.socket.close (), I suggest you try it yourself !
------ For reference only -------------------------------------- -
I'm here to write the code , just learning to use , does not suggest that you direct use projects, is just learning to use Oh !
correct code is as follows :
/*
* 服务端
*/
public class TestServer
{
public static void main(String[] args) throws IOException
{
System.out.println("服务端启动......");
ServerSocket server = new ServerSocket(8888);
Socket client = server.accept();
OutputStream output = client.getOutputStream();
InputStream input = client.getInputStream();
byte[] temp = new byte[10];
int realLen = 0;
while ((realLen = input.read(temp)) != -1)
{
System.out.println("【服务端】正在发送数据......");
output.write(temp, 0, realLen);
}
System.out.println("【客户端】发送数据完毕!");
output.flush();
client.close();
}
}
/*
* 客户端
*/
public class TestClient
{
public static void main(String[] args) throws UnknownHostException,
IOException
{
System.out.println("客户端启动......");
final Socket client = new Socket(InetAddress.getLocalHost(), 8888);
final OutputStream out = client.getOutputStream();
InputStream in = client.getInputStream();
final FileInputStream fileIn = new FileInputStream(new File(
"D:\\杂乱\\桌面.jpg"));
// 使用一个子线程发送数据
Thread handlerExecute = new Thread()
{
@Override
public void run()
{
try
{
byte[] fileTemp = new byte[1024];
int realFileLen = 0;
while ((realFileLen = fileIn.read(fileTemp)) != -1)
{
System.out.println("【客户端】正在发送数据......");
out.write(fileTemp, 0, realFileLen);
}
System.out.println("【客户端】发送数据完毕!");
out.flush();
client.shutdownOutput();
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
handlerExecute.start();
// 使用主线程接收数据
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
int realLen = 0;
byte[] temp = new byte[10];
while ((realLen = in.read(temp)) != -1)
{
byteArray.write(temp, 0, realLen);
}
byte[] recvByte = byteArray.toByteArray();
System.out.println("客户端接收消息成功,消息长度:" + recvByte.length);
}
}
everything there intact ! Thank guishuanglin again !!!
没有评论:
发表评论