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("校驗失敗");
}
}
}