一、TCP的基本概念
TCP是專門設計用于在不可靠的英特網上提供可靠的、端到端的位元組流通信的協定,是一個面向連接配接的協定,TCP連接配接是位元組流而非封包流。UDP和TCP各有65536個端口号互不影響。
二、單線程服務端
以下代碼隻能實作服務端和用戶端的同步對話。服務端處理完一個用戶端請求,才會處理另一個用戶端請求。伺服器端的輸出效果是Client1阻塞20秒,Client2不會執行。必須等Client1阻塞結束之後,Client2才會執行。該例子可用來學習TCP的基本文法。
/**
* TCP用戶端1
*
* @author 徐越
*/
public class Client1
{
public static void main(String[] args) throws Exception
{
Socket socket = new Socket("127.0.0.1", 8821);
OutputStream os = socket.getOutputStream();
String msg = "我是徐越1";
Thread.sleep(20000);
os.write(msg.getBytes());
os.flush();
os.close();socket.close();
}
}
* TCP用戶端2
public class Client2
String msg = "我是徐越2";
* 單線程TCP服務端
public class Server
// 建立端口為8821的TCP伺服器端對象
// 8821是伺服器端的端口号而用戶端從某端口A連到8821,端口A是随機的
ServerSocket serverSocket = new ServerSocket(8821);
while (true)
{
// 若無用戶端發送請求則線程在此阻塞,方法不繼續執行
Socket socket = serverSocket.accept();
System.out.println("connected");
InputStream instream = socket.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = instream.read(buffer)) != -1)
{
bos.write(buffer, 0, len);
}
instream.close();
bos.flush();
bos.close();
String msg = bos.toString();
System.out.println("用戶端的IP:" + socket.getInetAddress().getHostAddress());
System.out.println("用戶端的端口:" + socket.getPort());
System.out.println("用戶端的資訊:" + msg);
}
}
執行結果
connected
用戶端的IP:127.0.0.1
用戶端的端口:3775
用戶端的資訊:我是徐越1
用戶端的端口:3787
用戶端的資訊:我是徐越2
三、多線程伺服器
在實際應用中是在伺服器上運作一個永久的程式,接收來自其他多個用戶端的請求,提供相應的服務。需要利用多線程實作多客戶機制。伺服器在指定的端口上監聽是否有客戶請求,一旦監聽到就會啟動一個專門的服務線程來響應該請求,而伺服器本身在啟動完線程之後馬上又進入監聽狀态,等待下一個客戶的到來。隻要将服務端為如下代碼,Client1和Client2就會異步執行。
* 多線程服務端0
public class MultiThreadServer0
// 端口号
private int port = 8821;
// 服務端
private ServerSocket serverSocket;
public MultiThreadServer0() throws IOException
// 建立伺服器端
serverSocket = new ServerSocket(port);
System.out.println("伺服器啟動");
public void service()
Socket socket = null;
try
// 用戶端進行連接配接時會觸發accept方法進而建立連接配接
socket = serverSocket.accept();
new MultiThreadHandler(socket).start();
catch (Exception e)
e.printStackTrace();
public static void main(String[] args) throws IOException
new MultiThreadServer1().service();
* 多線程處理類
class MultiThreadHandler extends Thread
private Socket socket;
public MultiThreadHandler(Socket socket)
this.socket = socket;
private BufferedReader getReader(Socket socket) throws IOException
InputStream socketIn = socket.getInputStream();
// InputStreamReader為轉換流
// InputStream本是位元組流,現加一個Reader,表示用字元流的方式讀取位元組流
InputStreamReader isr = new InputStreamReader(socketIn);
return new BufferedReader(isr);
public void run()
try
BufferedReader br = getReader(socket);
String msg = null;
while ((msg = br.readLine()) != null)
System.out.println("用戶端的IP:" + socket.getInetAddress().getHostAddress());
System.out.println("用戶端的端口:" + socket.getPort());
System.out.println("用戶端的資訊:" + msg);
catch (IOException e)
e.printStackTrace();
finally
if (socket != null)
{
socket.close();
}
catch (IOException e)
* 多線程服務端1
public class MultiThreadServer1
// 線程池
private ExecutorService executorService;
// 單個CPU線程池大小
private final int POOL_SIZE = 10;
public MultiThreadServer1() throws IOException
// 擷取目前系統的CPU數目
int cpuNums = Runtime.getRuntime().availableProcessors();
// 根據系統資源情況靈活定義線程池大小
executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);
// 客戶進行連接配接就會觸發accept方法進而建立連接配接
// 調用線程池操作
executorService.execute(new Handler(socket));
class Handler implements Runnable
public Handler(Socket socket)
兩個多線程服務端執行結果相同
伺服器啟動
用戶端的端口:3931
用戶端的端口:3928
參考位址:http://www.2cto.com/kf/201209/158518.html
本文轉自IT徐胖子的專欄部落格51CTO部落格,原文連結http://blog.51cto.com/woshixy/1098701如需轉載請自行聯系原作者
woshixuye111