① java socket 、while(){} 循環後不執行下面的語句...
因為你這個式socket編程,輸入流肯定是從客戶端得到的,此時雖然已將客戶端傳過來的數據讀取完畢,但服務端仍舊在運行,監聽客戶端的狀態,並等待客戶端再次發開數據,所以輸入流此時並沒有關閉,程序此時處於等待狀態,while循環並沒有跳出!所以後邊的輸出語句就不會執行到!
② java socket 如何發送一個結構體消息,java中結構體是個什麼概念...
有一個socket 程序,一端是c++寫的socket 服務程序
另一端是Java寫客戶端程序,兩者之間需要通信。
c++/c接收和發送的都是結構體,而Java是直接發送的位元組流或者byte 數組。
解決方法:c++/c socket 在發送結構體的時候其實發送的也是位元組流。因為結構體本身也是內存中的一塊連續數據。問題就變成了如何把結構體手動轉成位元組的問題了
採用類似的報頭:
// packet head
typedef struct tagPacketHead{
long PacketID;
long PacketLen;
}PacketHead;此時套介面的讀寫方式為先讀報頭,在報頭中取出數據負載的長度,然後再讀相應位元組的數據。
包頭後面跟上包體,其中包體的長度,就是上面結構體中的PacketLen,Clinet首先接受包頭,因為包頭是兩邊約定好的,所以可以直接Receive一個定長的消息,也就是這個包頭的長度的消息,從包頭中取得包體的長度後,就可以再次Receive一個包體長度的消息了。那麼Java中如何發送一個結構體呢?下面是解決方法:
使用C/S模式,Client為VC6開發,Server為Java,通過Socket通信。
package org.charry.org;
import java.net.*;
/**
*
* 位元組轉換,參考網路文章
*/
class Packet {
private byte[] buf = null;
/**
* 將int轉為低位元組在前,高位元組在後的byte數組
*/
private static byte[] toLH(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 將float轉為低位元組在前,高位元組在後的byte數組
*/
private static byte[] toLH(float f) {
return toLH(Float.floatToRawIntBits(f));
}
/**
* 構造並轉換
*/
public Packet(int packetID, int packetLen, String packetBody) {
byte[] temp = null;
buf = new byte[packetBody.getBytes().length + 8];
temp = toLH(packetID);
System.array(temp, 0, buf, 0, temp.length);
temp = toLH(packetLen);
System.array(temp, 0, buf, 4, temp.length);
System.array(packetBody.getBytes(), 0, buf, 8, packetBody.length());
}
/**
* 返回要發送的數組
*/
public byte[] getBuf() {
return buf;
}
/**
* 發送測試
*/
public static void main(String[] args) {
try {
String tmp = 「test string!」;
Socket sock = new Socket(」127.0.0.1″, 8888);
sock.getOutputStream().write(
new Packet(123, tmp.length(), tmp).getBuf());
sock.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
如果需要用Java 接收結構體的話只需要將上面過程逆過來即可。
③ 使用Java 1用socket程序發送和接收位元組數組 2用十六進制的形式顯示每個位元組裡面的內容
我們定義發送者和接收者,發送者作為客戶端,接收者作為服務端。
Sender.java
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
importjava.util.Arrays;
publicclassSender{
in(String[]args)throwsException{
//127.0.0.1代表本機地址,在8888埠上監聽
Sendersender=newSender("127.0.0.1",8888);
byte[]bytes={15,16,17,120};//對應的十六進制是0F101178
sender.send(bytes);
System.out.println("發送"+Arrays.toString(bytes)+"完畢!");
}
privatefinalStringhost;
privatefinalintport;
publicSender(Stringhost,intport){
this.host=host;
this.port=port;
}
privatevoidsend(byte[]bytes)throwsIOException{
Socketsocket=newSocket(host,port);//建立和服務端的socket
try(DataOutputStreamdos//建立輸出流
=newDataOutputStream(socket.getOutputStream())){
dos.write(bytes,0,bytes.length);//向輸出流寫入bytes
}
}
}
Receiver.java
importjava.io.DataInputStream;
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
publicclassReceiver{
publicstaticvoidmain(String[]args)throwsException{
Receiverreceiver=newReceiver(8888);
receiver.receive();
}
;
publicReceiver(intport)throwsIOException{
serverSocket=newServerSocket(port);
}
privatevoidreceive()throwsIOException{
System.out.println("等待客戶端連接...");
Socketsocket=serverSocket.accept();
try(DataInputStreamdis=newDataInputStream(socket.getInputStream())){
byte[]bytes=newbyte[1024];//假設發送的位元組數不超過1024個
intsize=dis.read(bytes);//size是讀取到的位元組數
Stringhex=bytesToHex(bytes,0,size);
System.out.println("接收到的byte數組的十六進制:"+hex);
}
}
/**
*將byte數組轉化為十六進制字元串
*
*@parambytesbyte[]數組
*@parambegin起始位置
*@paramend結束位置
*@returnbyte數組的十六進制字元串表示
*/
privateStringbytesToHex(byte[]bytes,intbegin,intend){
StringBuilderhexBuilder=newStringBuilder(2*(end-begin));
for(inti=begin;i<end;i++){
hexBuilder.append(Character.forDigit((bytes[i]&0xF0)>>4,16));//轉化高四位
hexBuilder.append(Character.forDigit((bytes[i]&0x0F),16));//轉化低四位
hexBuilder.append('');//加一個空格將每個位元組分隔開
}
returnhexBuilder.toString().toUpperCase();
}
}
運行,首先啟動服務端:
④ java socket輸入流inputStream.read(byte[])方法一次讀入多幀數據,也就是多幀數據連在一起
因為inputStream.read(byte)是盡可抄能的讀byte[]大小的數據襲,當你的服務端發送數據速度大於客戶端讀取數據的速度時,就會出現客戶端讀到多幀連在一起的報文。而這些發送數據,讀取數據的速度是未知的。所以我們需要人為的來做一些調整。比如說每一幀作為一行寫入Socket,客戶端每次從socket讀取一行。這樣客戶端每次都是讀取一幀。
以上情況可以這樣實現:在服務端使用PrintWriter
PrintWriterwriter=newPrintWriter(socket.getOutputStream());
writer.println(data);
客戶端可以使用BufferedReader
BufferedReaderreader=newBufferedReader(newBufferedInputStream(socket.getInputStream()));
Strings=reader.readLine();
⑤ java的socket流的read問題
HTTP協議是有固定格式的,由Header + Body組成,你可以先去看看相關協議說明。
讀取時應該先通過連續2個換行符分割header和body,然後在header里查Content-Length,根據ContentLength才知道body到底有多長,這樣你才能從流中把一個個http包分割出來。
對於chunk模式,在最後會有一個長度為0的chunk標識,來指示響應已結束。
⑥ java伺服器端用傳輸給客戶端文件流(fileinputstream),客戶端應該如何接收(socket )
其實這個問題你應該先想一下socket到底是一個什麼東西,在網路編程中socket到底用來做什麼的。socket:在操作系統內核中它代表網路連接的一個端點(endpoint),在應用程序中它代表一個打開的文件。socketpair唯一確定的一條網路連接,socketpair就是客戶端socket和服務端socket的一個組合。也就是客戶端ip和port與服務端ip和port的組合。一條網路連接也就是一條通信的信道,tcp連接代表的信道是全雙工的。以信道來講,邏輯上就存在兩個管道來代表輸出與輸入來發送和接收信息。
那麼在應用程序上我們就可以拿到這2個管道來完成socket之間的通信。
以你的應用來看輸出流fos就代表著圖中的紅色管道,那麼在服務端就應該是這個樣的。
ScoketconnSock=serverSocket.accept();//connSock代表著服務端的Socket
InputStreamis=connSock.getInputStream();//輸入流is代表圖中的紅色管道
OutputStreaos=connSock.getOutputStream();//輸出流os代表圖中的綠色管道
在服務端有一個位元組緩沖區來存放從is讀取的位元組數據
byte[]buffer=newbyte[1024];
然後服務端讀取數據來填充這個位元組緩沖區
is.read(buffer);//比如這樣
然後就根據你的需求來操作這個buffer了。
然後把處理過後的數據通過os發送給客戶端。os就是圖中的那個綠色管道
os.write(處理過後的數據);
⑦ java-socket 如何判斷網路傳過來的是字元串還是對象
socket建立連接的getInputstream()和getOutputStream()方法都是位元組流。
可以通過writeUTF等方法來進行寫入。
如果想判斷是字元串還是對象,你可以對對象進行一下處理。這個對象是某個類的實例,這個類裡面定義一個標識屬性,比如public int flag,通過位元組流進行交流後,這邊讀取到,首先讀取一個int數據,如果是1或者是你令的別的標志,那麼就是對象,按對象處理。如果readInt後不能轉化為你要求的那個標識,那麼就是字元串。用public boolean flag等也可。
都是位元組流過來的,讀取規定位元組數看看是不是你事先定好的標志。