TCP客户端和服务端
先寫服務端,一定要先執(zhí)行服務端
package wangluobiancheng;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
/*
?* TCP通信嚴格區(qū)分客戶端和服務器端,在通信時必須先由客戶端去連接服務器端才能實現(xiàn)通信,服務器端不能主動連接客戶端
?* 并且服務器端程序要先啟動,等待客戶端的連接
?* ServerSocket類,用于表示服務器端,通信時要先創(chuàng)建代表服務器端的ServerSocket對象,相當于開啟一個服務,此服務會等待客戶端的連接。
?* Server類,表示客戶端,創(chuàng)建Server對象,使用該對象向服務器端發(fā)出連接請求,服務器端響應后,客戶端再次向服務器端發(fā)送確認信息,確認連接
?* ServerSocket()使用該構(gòu)造方法在創(chuàng)建ServerSocket對象時,并沒有綁定端口號,這樣的對象創(chuàng)建的服務器端沒有監(jiān)聽任何端口,不能直接使用
?* *最常用ServerSocket(int port)可以將其綁定到一個指定的端口號上(參數(shù)port就是端口號)。客戶端需要指定的端口號來訪問服務器端程序
?* ServerSocket(int port,int backlog)可以將其綁定到一個指定的端口號上(參數(shù)port就是端口號)。客戶端需要指定的端口號來訪問服務器端程序,backlog用于指定在
?* 服務器忙時,可以與之保持連接請求的等待客戶數(shù)量,如果沒有指定這個參數(shù),默認為50
?* ServerSocket(int port,int backlog,InetAddress bindAddr)bindAddr用于指定相關的IP地址,該構(gòu)造方法的使用適用于計算機上有多塊網(wǎng)卡和多個IP的情況
?* 使用時可以明確規(guī)定ServerSocket在哪塊網(wǎng)卡或IP地址上等待客戶的連接請求。
?*/
?? ?public static void main(String[] args) throws Exception {
//?? ??? ?創(chuàng)建TCPServer對象,并調(diào)用listen()方法
?? ??? ?TCPServer tcpss=new TCPServer();
?? ??? ?tcpss.listen();
?? ?}
}
/*//TCP服務端
class TCPServer{
?? ?private static final int PORT = 7788;//定義一個端口號
?? ?public void listen() throws Exception {
//?? ??? ?創(chuàng)建ServerSocket(服務器)對象,指定端口PORT,即7788
?? ??? ?ServerSocket s = new ServerSocket(PORT);
//?? ??? ?Socket accept()該方法用于等待客戶端的連接,在客戶端連接之前會一直處于阻塞狀態(tài),如果有客戶端連接,就會返回一個與之對應的Socket對象,就是服務器也會創(chuàng)建一個Socket對象,去和客戶端的Socket對象對應
//?? ??? ?調(diào)用ServerSocket的accept()方法接受客戶端的請求,執(zhí)行accept()方法之后程序會發(fā)生阻塞,直到客戶端發(fā)出連接請求時,accept()會返回一個與之對應的Socket對象,用于和客戶端實現(xiàn)通信
?? ??? ?Socket client = s.accept();
?? ??? ?OutputStream os = client.getOutputStream();//創(chuàng)建輸出流對象,向客戶端輸出數(shù)據(jù)
?? ??? ?System.out.println("開始與客戶端交互數(shù)據(jù)");
//?? ??? ?當客戶端連接到服務端時,向客戶端輸出數(shù)據(jù)。("傳智博客歡迎你!").getBytes()將定義的字符串轉(zhuǎn)換為字節(jié)數(shù)組
?? ??? ?os.write( ("傳智博客歡迎你!").getBytes() );
?? ??? ?Thread.sleep(5000);//模擬執(zhí)行其他功能占用的時間
?? ??? ?System.out.println("結(jié)束與客戶端交互數(shù)據(jù)");
?? ??? ?os.close();//關閉緩沖區(qū)
?? ??? ?client.close();//關閉客戶端與服務器的連接
?? ?}
}*/
/*
?* 上面的程序分別實現(xiàn)了服務器端程序和客戶端程序,當一個客戶端程序請求服務器端時,服務器端就會結(jié)束阻塞狀態(tài),完成程序的運行
?* 實際上,很多服務器端程序都是允許被多個應用程序訪問的,例如門戶網(wǎng)站可以被多個用戶同時訪問,因此服務器都是多線程的
?* 多個客戶端訪問同一個服務器端,服務器端為每個客戶創(chuàng)建一個對應的Socket,并且開啟一個新的線程使兩個Socket(一個是客戶端的,一個是服務器端的)建立專線進行通信
?*/
//TCP服務端
class TCPServer{
?? ?private static final int PORT = 7788;//定義一個端口號
?? ?public void listen() throws Exception {
//?? ??? ?創(chuàng)建ServerSocket(服務器)對象,指定端口PORT,即7788
?? ??? ?ServerSocket s = new ServerSocket(PORT);
//?? ??? ?使用while循環(huán)不停的接受客戶端發(fā)送的請求
?? ??? ?while(true) {
//?? ??? ?Socket accept()該方法用于等待客戶端的連接,在客戶端連接之前會一直處于阻塞狀態(tài),如果有客戶端連接,就會返回一個與之對應的Socket對象
//?? ??? ?調(diào)用ServerSocket的accept()方法接受客戶端的請求,執(zhí)行accept()方法之后程序會發(fā)生阻塞,直到客戶端發(fā)出連接請求時,accept()會返回一個與之對應的Socket對象,用于和客戶端實現(xiàn)通信
?? ??? ?Socket client = s.accept();
//?? ??? ?下面的代碼用來開啟一個新的線程
?? ??? ?new Thread() {
?? ??? ??? ?public void run() {
?? ??? ??? ??? ?OutputStream os;//定義一個輸出流對象
?? ??? ??? ??? ?try {
?? ??? ??? ??? ??? ?os = client.getOutputStream();//獲取客戶端的輸出流
?? ??? ??? ??? ??? ?System.out.println("開始與客戶端交互數(shù)據(jù)");
?? ??? ??? ??? ??? ?os.write(("傳智播客歡迎您!").getBytes());
?? ??? ??? ??? ??? ?Thread.sleep(5000);//使線程休眠5000毫秒
?? ??? ??? ??? ??? ?System.out.println("結(jié)束與客戶端交互數(shù)據(jù)");
?? ??? ??? ??? ??? ?os.close();//關閉輸出流
?? ??? ??? ??? ??? ?client.close();//關閉Socket對象
?? ??? ??? ??? ?}catch(Exception e) {
?? ??? ??? ??? ??? ?e.printStackTrace();
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ???? }.start();
?? ??? ?}
?? ?}
}
再寫客戶端。(就是再建一個java文件)
package wangluobiancheng;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
/*
?* Socket用于實現(xiàn)TCP客戶端程序
?* Socket()該構(gòu)造方法在創(chuàng)建Socket對象時,并沒有指定IP地址和端口號,也就意味著只創(chuàng)建了客戶端對象,并沒有連接任何服務器。
?* 通過該構(gòu)造方法創(chuàng)建對象后還需調(diào)用connect(SocketAddress endpoint)方法,才能完成與指定服務器端的連接。其中參數(shù)endpoint用于封裝IP地址和端口號
?*/
?? ?public static void main(String[] args) throws Exception {
?? ??? ?TCPClient tcpc = new TCPClient();
?? ??? ?tcpc.connect();//創(chuàng)建TCPClient對象,并調(diào)用connect()方法
?? ?}
}
class TCPClient{
?? ?private static final int PORT = 7788;//服務端的端口號
?? ?public void connect() throws Exception {
//?? ??? ?Socket(InetAddress address,int port)該構(gòu)造方法在創(chuàng)建Socket對象時,指明IP地址和端口號
//?? ??? ?創(chuàng)建一個Socket(客戶端)并連接到給出地址和端口號的計算機
?? ??? ?Socket client = new Socket(InetAddress.getLocalHost(),PORT);
?? ??? ?InputStream is = client.getInputStream();//創(chuàng)建輸入流對象,client.getInputStream()用來接受服務器發(fā)來的數(shù)據(jù)
//?? ??? ?定義1024個字節(jié)數(shù)組
?? ??? ?byte[] buf = new byte[1024];
?? ??? ?int len = is.read(buf);//將數(shù)據(jù)讀取到緩沖區(qū)
?? ??? ?System.out.println( new String(buf,0,len) );//將緩沖區(qū)中的數(shù)據(jù)打印
//?? ??? ?關閉Socket對象,即關閉連接,釋放資源
?? ??? ?client.close();
?? ?}
}
服務器文件執(zhí)行后
客戶端執(zhí)行后
?
總結(jié)
以上是生活随笔為你收集整理的TCP客户端和服务端的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内核中的竞争状态和互斥(简述)
- 下一篇: 中班机器人上课视频_家委会:出班费买智能