網絡編程TCP

TCP特點:

1.面向連接的傳輸服務

        程序在用TCP協議傳輸數據時 需在源進程端口與目的進程端口之間建立一條TCP傳輸連接

2. 支持字節流的傳輸

    TCP在傳輸過程中將程序提交的數據看成一連串 無結構的字節流,因此接收端程序數據字節的起始與終結位置必須有程序自己確定

3.支持雙全工通信

    TCP運行通信雙方的程序在任何時候都可以發送數據

4.支持同事建立多個併發的TCP連接

5.支持可靠的傳輸服務

    使用確認機制檢查數據是否安全和完整的到達 並提供擁塞控制功能


TCP連接是3次握手 釋放是4次握手 可以通過wireshark抓包

Client客戶端:

public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException{
		//創建客戶端socket對象 指定目的主機和端口
		Socket socket=new Socket("192.168.xx.xxx",20000);
		//爲了發送數據 應該獲取socket中的流
		OutputStream out=(OutputStream) socket.getOutputStream();
		out.write("tcp client".getBytes());
		socket.close();
	}
}

Server服務端

public static void main(String[] args) throws UnknownHostException, IOException{
		//建立服務端的socket服務 並監聽端口
		ServerSocket server=new ServerSocket(20000);
		//獲取鏈接過來的客戶端對象 沒有連接就等待 這個方法是阻塞式的
		Socket socket=server.accept();
		String ip=socket.getInetAddress().getHostAddress();
		System.out.println("ip: "+ip);
		//如果客戶端發送數據 服務器就可以根據對應的客戶端對象 獲取到該對象的讀取流來讀取數據
		InputStream in=socket.getInputStream();
		byte[] buff=new byte[1024];
		int len=in.read(buff);
		System.out.println(new String(buff,0,len));
		
		//關閉客戶端
		socket.close();
		//服務器關閉(可選操作)
		server.close();
		
	}

編譯運行



如果想要收到服務端返回給客戶端值則需要在客戶端中添加

InputStream in=socket.getInputStream();
		byte[] buff=new byte[1024];
		int len=in.read(buff);
		System.out.println(new String(buff,0,len));

服務端中加

OutputStream out=socket.getOutputStream();
		out.write("返回".getBytes());
TCP複製文件

客戶端:

public class TextClient {
	public static void main(String[] args) throws IOException{
		Socket s=new Socket("192.168.43.152",20000);
		System.out.println(s.getInetAddress().getHostAddress()+".. contected");
		BufferedReader bufr=new BufferedReader(new FileReader("UserTest.java"));
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		String line=null;
		while((line=bufr.readLine())!=null){
			out.println(line);
		}
		//必須shutdown 不然上面while結束後 下面的讀入流 中readline 回和server裏的while互相等待
		s.shutdownOutput();//關閉客戶端輸出流 相當於給流中加入一個結束標記-1
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()))	;
		System.out.print(bufIn.readLine());
		bufr.close();
		s.close();
	}
}

服務端:

public class TextServer {
	public static void main(String[] args) throws IOException{
		ServerSocket ss=new ServerSocket(20000);
		Socket s=ss.accept();
		System.out.println(s.getInetAddress().getHostAddress()+".. contected");
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		PrintWriter out=new PrintWriter(new FileWriter("server.txt"),true);
		String line=null;
		while((line=bufIn.readLine())!=null){
			out.println(line);
		}
		PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
		pw.println("success");
		out.close();
		s.close();
		ss.close();
	}
}

併發上傳圖片

客戶端:

public class PicClient {
	public static void main(String[] args) throws UnknownHostException, IOException{
		if(args.length!=1){
			System.out.println("請選擇一個png圖片");
			return;
		}
		File file=new File(args[0]);
		if(!(file.exists() & file.isFile())){
			System.out.println("文件有問題或不存在或不是文件");
			return;
		}
		if(!file.getName().endsWith(".png")){
			System.out.println("圖片格式錯誤");
			return;
		}
		if(file.length()>1024*1024*8){
			System.out.println("文件超過8M");
			return;
		}
		Socket socket=new Socket("192.168.xx.xxx",20000);
		FileInputStream fis=new FileInputStream(file);
		OutputStream out=socket.getOutputStream();
		byte[] buf=new byte[1024];
		int len=0;
		while((len=fis.read(buf))!=-1){
			out.write(buf,0,len);
		}
		socket.shutdownOutput();
		InputStream in=socket.getInputStream();
		byte[] bufIn=new byte[1024];
		int num=in.read(bufIn);
		System.out.println(new String(bufIn,0,num));
	}
}

服務端:要有線程

public class PicServer {
	public static void main(String[] args) throws IOException{
		ServerSocket ss=new ServerSocket(20000);
		while(true){
			Socket s=ss.accept();
			new Thread(new PicThread(s)).start();
		}
	}
	
}
class PicThread implements Runnable{
	private Socket s;
	PicThread(Socket s){
		this.s=s;
	}
	public void run() {
		int count=0;
		String ip=s.getInetAddress().getHostAddress();
		try{
			System.out.println(ip+"...contected");
			InputStream in=s.getInputStream();
			//防止覆蓋
			File file=new File(ip+"("+(count)+")"+".png");
			while(file.exists()){
				file=new File(ip+"("+(count++)+")"+".png");
			}
			FileOutputStream fos=new FileOutputStream(file);
			byte[] buf=new byte[1024];
			int len=0;
			while((len=in.read(buf))!=-1){
				fos.write(buf,0,len);
			}
			OutputStream out=s.getOutputStream();
			out.write("上傳成功".getBytes());
			fos.close();
		}catch(Exception e){
			throw new RuntimeException("上傳失敗");
		}
	}
	
}

併發登錄
public class loginClient {
	/*客戶端通過鍵盤錄入的方式登錄 服務端驗證
	 * 如果該用戶存在 在服務器端顯示 xxx已登錄
	 * 在客戶端顯示 歡迎登錄
	 *  不存在 服務端 顯示 xxx嘗試登錄
	 *  客戶端顯示 用戶不存在
	 *  最多登錄3次
	 * */
	public static void main(String[] args) throws UnknownHostException, IOException{
		Socket socket=new Socket("192.168.43.152",20000);
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out=new PrintWriter(socket.getOutputStream(),true);
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
		for(int i=0;i<3;i++){
			String line=bufr.readLine();
			if(line==null)
				break;
			out.println(line);
			String info=bufIn.readLine();
			System.out.println("info: "+info); 
			if(info.contains("歡迎"))
				break;
		}
		bufr.close();
		socket.close();
	}
}
class loginServer{
	public static void main(String[] args) throws IOException{
		ServerSocket ss=new ServerSocket(20000);
		while(true){
			Socket s=ss.accept();
			new Thread(new UserThread(s)).start();
		}
	}
}
class UserThread implements Runnable{
	private Socket s;
	public UserThread(Socket s){
		this.s=s;
	}
	public void run() {
		String ip=s.getInetAddress().getHostName();
		System.out.println(ip+" ....connected");
		try{
			for(int i=0;i<3;i++){
				BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
				String name=bufIn.readLine();
				if(name==null){
					break;
				}
				BufferedReader bufr=new BufferedReader(new FileReader("user.txt"));
				PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
				String line=null;
				boolean flag=false;
				while((line=bufr.readLine())!=null){
					if(line.equals(name)){
						flag=true;
						break;
					}
				}
				if(flag){
					System.out.println(name+",已登錄");
					out.println(name+",歡迎光臨");
					break;
				}else{
					System.out.println(name+",嘗試登錄");
					out.println(name+",用戶名不存在");
				}
			}
			s.close();
		}catch(Exception e){
			throw new RuntimeException("校驗失敗");
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章