① 如何干凈的實現Android/java Socket 長連接通信
Java Socket通信有很多的時候需要我們不斷的學習。方面效率雖然不及C與C++但它以靈活語言優勢,為大家廣為使用。 本文就對在使用java做通信方面程序時候應改注意問題做以說明。1.長連接、短鏈接只是針對客戶端而言,伺服器無所謂長、短;2.無論同步或者非同步通信,發送之後務必要又響應回復,確認收到,負責進行一定范圍內重發,例如重發三次;3.長連接伺服器與客戶端之間務必需要心跳探測,由客戶端主動發起;4.短連接伺服器通用代碼:
package com.biesan.sms.gate.unioncom.communication;
import com.biesan.commons.Constants;
import com.biesan.commons.util.CodeUtil;
import com.biesan.sms.gate.unioncom.data.*;
import com.biesan.sms.gate.unioncom.util.GateInfo;
import java.net.*;
import java.io.*;
import java.util.*;
import org.apache.log4j.*;
import spApi.*;
public class UnioncomDeliver extends Thread {
// stop flag
private boolean unInterrupt = true;
private boolean unErr = true;
//private boolean closeSocketFlag = false;
// server socket
private ServerSocket serverSo = null;
// current socket
private Socket so = null
private OutputStream output = null;
private InputStream input = null;
// gate command
private SGIP_Command tmpCmd = null;
private SGIP_Command cmd = null;
private Bind bind = null;
private BindResp bindResp = null;
//private Unbind unBind = null;
private UnbindResp unBindResp = null;
private boolean unAcceptErrorFlag = true;
Logger unioncomLog = Logger.getLogger(Unioncom
Deliver.class.getName());
public UnioncomDeliver() {
}
public void run() {
unioncomLog.info("Start...");
while (unInterrupt) {
this.initServer();
this.startServices();
while (this.unAcceptErrorFlag) {
try {
//接受連接請求
unioncomLog.info("before accept connection!.......
FreeMemroy :" + Runtime.getRuntime().freeMemory());
this.acceptConnection();
unioncomLog.info("after accept connection!.......
FreeMemroy :" + Runtime.getRuntime().freeMemory());
while (unErr) {
cmd = new Command();
unioncomLog.info("before read command from stream
........... FreeMemroy: " + Runtime.getRuntime().
freeMemory());
tmpCmd = cmd.read(input);
unioncomLog.info("after read command from stream " +
getCommandString(cmd.getCommandID()) + " FreeMemroy: " +
Runtime.getRuntime().freeMemory());
if (tmpCmd == null) {
unErr = false;
break;
}
switch (cmd.getCommandID()) {
// biad ready communication
case SGIP_Command.ID_SGIP_BIND: {
this.dealBind();
break;
}// exit bind
case SGIP_Command.ID_SGIP_UNBIND: {
this.dealUnBind();
unioncomLog.info("after unbind connection!.......
FreeMemroy :" + Runtime.getRuntime().freeMemory());
break;
}// deliver
....
default : //錯誤的命令字
break;
}// switch
}// while(unErr)
} catch (Exception e) {
unioncomLog.error("Unioncom Recv Service Error"
+ e.getMessage());
} finally {
if (this.so != null) {
this.closeSocket();
}
this.unErr = true;
}
}// while (this.unAcceptErrorFlag)
try {
this.closeServerSocket();
sleep(200);// sleep
} catch (InterruptedException ie) {
}
}// while(unInterrupt)
}
private String getCommandString(int cmd){
switch (cmd) {
// biad ready communication
case SGIP_Command.ID_SGIP_BIND: {
return " BIND COMMAND ";
}// exit bind
case SGIP_Command.ID_SGIP_UNBIND: {
return " UNBIND COMMAND ";
}// deliver
case ...
default:
return " UNKNOWN COMMAND";
}
}
private void dealBind() {
try {
bind = new Bind(tmpCmd);
if (bind.readbody() != 0) {
unioncomLog.warn("Read Bind error");
this.unErr = false;
}
bindResp = new BindResp(tmpCmd.getMsgHead());
bindResp.SetResult(0);
bindResp.write(output);
unioncomLog.debug("Bind success!");
} catch (Exception e) {
unioncomLog.error("Dela Union Recv Bind Error!" +
e.getMessage());
this.unErr = false;
}
}
private void dealUnBind() {
try {
//unBind = (Unbind) tmpCmd;
unBindResp = new UnbindResp(tmpCmd.getMsgHead());
unBindResp.write(output);
unioncomLog.debug("UnBind success!");
} catch (Exception e) {
unioncomLog.warn("Unbind error!" + e.getMessage());
}
this.unErr = false;
}
private void startServices() {
boolean unStartServices = true;
while (unStartServices) {
try {
serverSo = new ServerSocket(ugInfo.getLocalServerPort(), 5,
InetAddress.getByName(ugInfo.getLocalIpAdd()));
//serverSo.setSoTimeout(60000);
unStartServices = false;
unioncomLog.info("Create union recv socket Ok!");
} catch (IOException e) {
unioncomLog.warn("Create union recv socket error!"
+ e.getMessage());
unStartServices = true;
UnioncomSubmit.thrSlp(3000);
}
}
}
private void acceptConnection() {
// Accept 失敗
try {
so = serverSo.accept();
so.setSoTimeout(10000);
} catch (Exception e) {
unioncomLog.warn("Accept Error!" + e.getMessage());
this.closeServerSocket();
this.unAcceptErrorFlag = false;
this.unErr=false;
}
// Accept成功
try {
input = so.getInputStream();
output = so.getOutputStream();
} catch (IOException e) {
unioncomLog.warn("Get I/O stream Error!" + e.getMessage());
this.closeService();
this.unAcceptErrorFlag = false;
this.unErr=false;
}
}
private void closeSocket() {
try {
so.close();
unioncomLog.info("Socket Close Success!!!");
} catch (Exception e) {
unioncomLog.error("Socket Close Failure!!!" + e.getMessage());
}
}
private void closeServerSocket() {
try {
serverSo.close();
unioncomLog.info("ServerSocket Close Success!!!");
} catch (Exception e) {
unioncomLog
.error("ServerSocket Close Failure!!!" + e.getMessage());
}
}
private void closeService() {
this.closeSocket();
this.closeServerSocket();
}
private void initServer() {
this.bind = null;
this.bindResp = null;
//this.unBind = null;
this.unBindResp = null;
this.tmpCmd = null;
this.cmd = null;
this.serverSo = null;
this.so = null;
this.output = null;
this.input = null;
this.unErr = true;
//this.closeSocketFlag = false;
unioncomLog.info("Memory***==="
+ java.lang.Runtime.getRuntime().freeMemory());
}
public synchronized void requireStop() {
this.unInterrupt = false;
unioncomLog.info("Requre interrupt!!!");
}
public String convertMsgContentCoding
(int msgCoding, byte[] msgContent) {
String deliverContent = null;
try {
if (msgContent != null) {
if (msgCoding == 8) { // 處理ucs32編碼
deliverContent = new String(msgContent,
"UnicodeBigUnmarked");
} else if (msgCoding == 0) { // 處理ASCII編碼
deliverContent = new String(msgContent, "ASCII");
} else if (msgCoding == 4) { // 處理binary編碼
deliverContent = new String(msgContent);
} else if (msgCoding == 15) { // 處理GBK編碼
deliverContent = new String(msgContent, "GBK");
// 處理DELIVER數據包的簡訊息ID
} else {
unioncomLog.error("編碼格式錯誤!");
return "";
}
} else
return "";
return deliverContent;
} catch (UnsupportedEncodingException ex) {
unioncomLog.error("deal content error!" +
ex.getMessage());
return "";
}
}
}
② java中的socket是什麼意思
所謂socket通常也稱作"套接字",用於描述IP地址和埠,是一個通信鏈的句柄。應用程序通常通過"套接字"向網路發出請求或者應答網路請求。
以J2SDK-1.3為例,Socket和ServerSocket類庫位於java.net包中。ServerSocket用於伺服器端,Socket是建立網路連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話。對於一個網路連接來說,套接字是平等的,並沒有差別,不因為在伺服器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。
重要的Socket API:
java.net.Socket繼承於java.lang.Object,有八個構造器,其方法並不多,下面介紹使用最頻繁的三個方法,其它方法大家可以見JDK-1.3文檔。
. Accept方法用於產生"阻塞",直到接受到一個連接,並且返回一個客戶端的Socket對象實例。"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,然後程序繼續;通常"阻塞"是由循環產生的。
. getInputStream方法獲得網路連接輸入,同時返回一個InputStream對象實例。
. getOutputStream方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。
注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,因為它們返回的流對象,通常都會被另一個流對象使用。
2ServerSocket類例子編輯
package com.lanber.socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
/**
* 注意:Socket的發送與接收是需要同步進行的,即客戶端發送一條信息,伺服器必需先接收這條信息,
* 而後才可以向客戶端發送信息,否則將會有運行時出錯。
* @param args
*/
public static void main(String[] args) {
ServerSocket ss = null;
try {
ss = new ServerSocket(8888);
//伺服器接收到客戶端的數據後,創建與此客戶端對話的Socket
Socket socket = ss.accept();
//用於向客戶端發送數據的輸出流
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//用於接收客戶端發來的數據的輸入流
DataInputStream dis = new DataInputStream(socket.getInputStream());
System.out.println("伺服器接收到客戶端的連接請求:" + dis.readUTF());
//伺服器向客戶端發送連接成功確認信息
dos.writeUTF("接受連接請求,連接成功!");
//不需要繼續使用此連接時,關閉連接
socket.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3客戶端的例子編輯
package com.lanber.socket;
importjava.io.DataInputStream;
import java.io.DataOutputStream;
importjava.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo {
/**
* @param args
*/
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("localhost",8888);
//獲取輸出流,用於客戶端向伺服器端發送數據
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//獲取輸入流,用於接收伺服器端發送來的數據
DataInputStream dis = new DataInputStream(socket.getInputStream());
//客戶端向伺服器端發送數據
dos.writeUTF("我是客戶端,請求連接!");
//列印出從伺服器端接收到的數據
System.out.println(dis.readUTF());
//不需要繼續使用此連接時,記得關閉哦
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
③ java如何實現基於TCP協議的socket傳輸
服務端監聽:ServerSocket server=new ServerSocket(port);//port:綁定的埠號
Socket client=server.accept();//監聽埠,一旦逗返神取得連接則獲世陵得客戶端的socket連接對象client
客戶端: Socket s=new Socket(ip,port);//要連接的伺服器的ip以及埠號
如果正常連接上之後,socket的對象可以獲得InputStream和OutputStreame,然後就可以進行通信了
完成通信山虧之後,執行socket對象的close()方法關閉連接,完成一次完整的socket連接
④ 關於用文本來實現Socket通信(java),求高手
這是服務辯罩器端:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.net.Socket;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JScrollPane;
public class J_ChatClient extends JFrame
{
private ObjectInputStream m_input; // 輸入流
private ObjectOutputStream m_output; //知橡 輸出流
private JTextField m_enter; // 輸入區域
private JTextArea m_display; // 顯示區域
public J_ChatClient( ) // 在圖形界面中攜猛鬧添加組件
{
super("聊天程序客戶端");
Container c = getContentPane( );
m_enter = new JTextField( );
m_enter.setEnabled( false );
m_enter.addActionListener(new ActionListener( )
{
public void actionPerformed( ActionEvent event )
{ // 向伺服器端發送數據
try
{
String s = event.getActionCommand( );
m_output.writeObject( s );
m_output.flush( );
mb_displayAppend( "客戶端: " + s );
m_enter.setText( "" ); // 清除輸入區域的原有內容
}
catch (Exception e)
{
System.err.println("發生異常:" + e);
e.printStackTrace( );
} // try-catch結構結束
} // 方法actionPerformed結束
} // 實現介面ActionListener的內部類結束
); // addActionListener方法調用結束
c.add( m_enter, BorderLayout.NORTH );
m_display = new JTextArea( );
c.add( new JScrollPane( m_display ), BorderLayout.CENTER );
} // J_ChatClient構造方法結束
public void mb_displayAppend( String s )
{
m_display.append( s + "\n" );
m_display.setCaretPosition( m_display.getText( ).length( ) );
m_enter.requestFocusInWindow( ); // 轉移輸入焦點到輸入區域
} // 方法mb_displayAppend結束
public boolean mb_isEndSession( String m )
{
if (m.equalsIgnoreCase("q"))
return(true);
if (m.equalsIgnoreCase("quit"))
return(true);
if (m.equalsIgnoreCase("exit"))
return(true);
if (m.equalsIgnoreCase("end"))
return(true);
if (m.equalsIgnoreCase("結束"))
return(true);
return(false);
} // 方法mb_isEndSession結束
public void mb_run( String host, int port)
{
try
{
mb_displayAppend("嘗試連接");
Socket s = new Socket(host, port);
String m; // 來自伺服器端的消息
m_output = new ObjectOutputStream( s.getOutputStream( ) );
m_input = new ObjectInputStream( s.getInputStream( ) );
m_enter.setEnabled( true );
do
{
m = (String) m_input.readObject( );
mb_displayAppend("伺服器端: " + m);
} while(!mb_isEndSession( m ));// do-while循環結束
m_output.writeObject("q"); // 通知服務端退出程序
m_output.flush( );
m_output.close( );
m_input.close( );
s.close( );
System.exit( 0 );
}
catch (Exception e)
{
System.err.println("發生異常:" + e);
e.printStackTrace( );
mb_displayAppend("發生異常");
} // try-catch結構結束
} // 方法mb_run結束
public static void main(String args[ ])
{
J_ChatClient app = new J_ChatClient( );
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(350, 150);
app.setVisible(true);
if ( args.length == 0 )
app.mb_run("localhost", 5000);
else app.mb_run(args[0], 5000);
} // 方法main結束
} // 類J_ChatClient結束
這是客戶端:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JScrollPane;
public class J_ChatServer extends JFrame
{
private ObjectInputStream m_input; // 輸入流
private ObjectOutputStream m_output; // 輸出流
private JTextField m_enter; // 輸入區域
private JTextArea m_display; // 顯示區域
private int m_clientNumber = 0; // 連接的客戶數
public J_ChatServer( ) // 在圖形界面中添加組件
{
super("聊天程序伺服器端");
Container c = getContentPane( );
m_enter = new JTextField( );
m_enter.setEnabled( false );
m_enter.addActionListener(new ActionListener( )
{
public void actionPerformed( ActionEvent event )
{ // 向客戶端發送數據
try
{
String s = event.getActionCommand( );
m_output.writeObject( s );
m_output.flush( );
mb_displayAppend( "伺服器端: " + s );
m_enter.setText( "" ); // 清除輸入區域的原有內容
}
catch (Exception e)
{
System.err.println("發生異常:" + e);
e.printStackTrace( );
} // try-catch結構結束
} // 方法actionPerformed結束
} // 實現介面ActionListener的內部類結束
); // addActionListener方法調用結束
c.add( m_enter, BorderLayout.NORTH );
m_display = new JTextArea( );
c.add( new JScrollPane( m_display ), BorderLayout.CENTER );
} // J_ChatServer構造方法結束
public void mb_displayAppend( String s )
{
m_display.append( s + "\n" ); //將給定文本追加到文檔結尾
//設置 TextComponent 的文本插入符的位置。注意,插入符可跟蹤更改,所以如果組件的基礎文本被更改,
//則此位置可能會移動。如果文檔為 null,則不執行任何操作。位置必須在 0 和組件的文本長度之間,否則將拋出異常
m_display.setCaretPosition( m_display.getText( ).length( ) );
m_enter.requestFocusInWindow( ); // 轉移輸入焦點到輸入區域
} // 方法mb_displayAppend結束
public boolean mb_isEndSession( String m )
{
if (m.equalsIgnoreCase("q"))
return(true);
if (m.equalsIgnoreCase("quit"))
return(true);
if (m.equalsIgnoreCase("exit"))
return(true);
if (m.equalsIgnoreCase("end"))
return(true);
if (m.equalsIgnoreCase("結束"))
return(true);
return(false);
} // 方法mb_isEndSession結束
public void mb_run( )
{
try
{
ServerSocket server = new ServerSocket(5000);
String m; // 來自客戶端的消息
while (true)
{
m_clientNumber++;
mb_displayAppend("等待連接[" + m_clientNumber + "]" + " ");
Socket s = server.accept( );
mb_displayAppend("接收到客戶端連接[" + m_clientNumber + "]" + " ");
m_output = new ObjectOutputStream( s.getOutputStream( ) );
m_input = new ObjectInputStream( s.getInputStream( ) );
m_output.writeObject("連接成功");
m_output.flush( );
m_enter.setEnabled( true );
do
{
m = (String) m_input.readObject( );
mb_displayAppend("客戶端: " + m);
} while(!mb_isEndSession( m ));// do-while循環結束
m_output.writeObject("q"); // 通知客戶端退出程序
m_output.flush( );
m_enter.setEnabled( false );
m_output.close( );
m_input.close( );
s.close( );
mb_displayAppend("連接[" + m_clientNumber + "]結束" + " ");
} // while循環結束
}
catch (Exception e)
{
System.err.println("發生異常:" + e);
e.printStackTrace( );
mb_displayAppend("連接[" + m_clientNumber +"]發生異常" + " ");
} // try-catch結構結束
} // 方法mb_run結束
public static void main(String args[ ])
{
J_ChatServer app = new J_ChatServer( );
app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
app.setSize(350, 150);
app.setVisible(true);
app.mb_run( );
} // 方法main結束
} // 類J_ChatServer結束
樓主看看就應該懂了,我注釋的很詳細的,這個是我以前學Socket編程的時候,寫的一個例子
⑤ JAVA TCP Socket埠的數據同步問題。
。。。 你方法錯了。 建議你先看看 ftp 的協議。 我簡單的說下 ftp 協議。
ftp 在客戶端連接上之後 ,客戶端 執行get 命令 服務端返回服務埠號,客戶端收到埠號 並根據埠號創喊胡租建連接, 連接建立成功後 服務端 直接讀取本地文件 通過數據流的方式邊讀邊將數據 輸出到 tcp 流,然後客戶端就是邊讀數據流邊寫入到本地。服務端將文件讀取完成之後 就close 數據流,客戶端就可以 捕獲到一個數據流關閉的異常,
再說 你的 問題。 socket is closed 就是 說tcp 已做薯經關閉了。 你還說 你使用了 shutdownoutput。。。。 這不是說 socket 停止的么? 停止了 還沒關閉? 已經被你的代碼關閉鄭兆了。!
⑥ 200分求JAVA 用socket進行文件的同步
客戶端,Client.java:
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = null;
String host = "127.0.0.1";
socket = new Socket(host, 4444);
File file = new File("M:\\test.xml");
// Get the size of the file
long length = file.length();
byte[] bytes = new byte[16 * 1024];
InputStream in = new FileInputStream(file);
OutputStream out = socket.getOutputStream();
int count;
while ((count = in.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
out.close();
in.close();
socket.close();
}
}
服務端,Server.java:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
Socket socket = null;
InputStream in = null;
OutputStream out = null;
try {
socket = serverSocket.accept();
} catch (IOException ex) {
System.out.println("Can't accept client connection. ");
}
try {
in = socket.getInputStream();
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
out = new FileOutputStream("M:\\test2.xml");
} catch (FileNotFoundException ex) {
System.out.println("File not found. ");
}
byte[] bytes = new byte[16*1024];
int count;
while ((count = in.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
out.close();
in.close();
socket.close();
serverSocket.close();
}
}
⑦ iOS socket怎麼和java通訊
SOCKET敲得例子,非常簡雀鋒單,TCP協議:
客戶端代碼:
import java.net.*;
import java.io.*;
public class SocketClient{
public static void main(String args[]){
try{
//客戶端連接伺服器
Socket socket1 = new Socket("127.0.0.1",1989);
InputStream is = socket1.getInputStream();
DataInputStream dis = new DataInputStream(is);
//客戶端接受服務首歲脊器端的信息
System.out.println(dis.readUTF());
dis.close();
socket1.close();
}
catch(IOException e){
System.out.println("IO異常");
}
}
}
伺服器代碼:
import java.net.*;
import java.io.*;
public class SocketServer{
public static void main(String args[]){
try{
ServerSocket ss = new ServerSocket(1989);
Socket socket1 = ss.accept();
OutputStream os = socket1.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
//伺服器端發給客者滲戶端的信息
dos.writeUTF("anyway,i need u!"+socket1.getInetAddress()+"port:"+socket1.getPort());
dos.close();
socket1.close();
}
catch(IOException e){
System.out.println("IO錯誤!");
}
}
}
⑧ JAVA客戶端與服務端Socket通信問題
你就發了一句話,怎麼能接受兩遍呢
改成這樣 String lin=null;
if((lin=dis.readUTF())!=null){
備談System.out.println(lin);
旦滾絕模姿}
這樣試試
⑨ Java 多線程 用socket通信
ServerSocket
server=new
ServerSocket(port);
/*..以下是監御首聽旦拆祥.*/
try{
while(true){
Socket
socket=server.accept(0;
Thread
handleThread=new
Thread(new
HandleRun(socket)).start();
//直接把跟客戶端連接的socket放到一個線程中處理。
//模搏之後,自己定義一個實現Runnable的HandleRun類即可(用於處理c-s之間的通信)
}
}catch(Exception
ex){}
看不懂的話,就追問。再不會的話,可以花點時間幫你寫個小小的Demo
⑩ JAVA Socket收發不同步
知隱桐蘆道為什麼延遲了嗎?
因為TCP的Nagle演算法使得發送的內容先被緩沖起來輪培,做了灶帶傳輸優化而導致的微小的延遲。
看看Java幫助文檔的Socket部分:
setTcpNoDelay
public void setTcpNoDelay(boolean on)
throws SocketException
啟用/禁用 TCP_NODELAY(啟用/禁用 Nagle 演算法)。
參數:
on - 為 true 表示啟用 TCP_NODELAY;為 false
表示禁用。
拋出:
SocketException -
如果底層協議出現錯誤,例如 TCP 錯誤。
從以下版本開始:
JDK1.1
另請參見:
getTcpNoDelay()