TCP传输协议
一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议 。
特点:
- 面向连接
- 点到点的通信
- 高可靠性
- 占用系统资源多、效率低
TCP编程
- 在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序
- 第一次通讯中等待连接的程序被称作服务器端(Server)程序
- TCP协议基于请求-响应模式
- 利用IO流实现数据的传输
简单服务器端程序实现
package io.github.tcp;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Serve {
public static void main(String[] args) throws IOException {
System.out.println("--------Serve----------");
// 实现了服务器套接字
ServerSocket serve=new ServerSocket(9999);
// 侦听要连接到此套接字并接受它。(阻塞式——即没有客户端通信请求,程序不向下运行)
Socket socket=serve.accept();
// 创建此套接字的输入流
DataInputStream dis=new DataInputStream(socket.getInputStream());
// 读取数据
String str=dis.readUTF();
// 显示数据信息
System.out.println(str);
// 释放资源
dis.close();
socket.close();
serve.close();
}
}
简单客户端程序实现
package io.github.tcp;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("---------Client-------------");
// 实现客户端套接字
Socket client=new Socket("localhost",9999);
// 创建此套接字的输出流。
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
//输出数据
String str="好爱好";
dos.writeUTF(str);
// 释放资源
dos.close();
client.close();
}
}
服务端客户端双向通信
TCP相较于UDP来说,TCP通信的套接字可以进行信息的发送和接收,而UDP要想进行信息的发送和接收则需要两个套接字。
服务端
package io.github.tcp;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Serve2 {
public static void main(String[] args) throws IOException {
System.out.println("--------Serve----------");
ServerSocket serve=new ServerSocket(9999);
Socket socket=serve.accept();
DataInputStream dis=new DataInputStream(socket.getInputStream());
String str=dis.readUTF();
String[] datas=str.split("&");
String name="";
String pwd="";
for(String info:datas) {
String[] values=info.split("=");
if(values[0].equals("name")) {
System.out.println("用户名为:"+values[1]);
name=values[1];
}
else if(values[0].equals("pwd")) {
System.out.println("密码为:"+values[1]);
pwd=values[1];
}
}
/********************* 服务端向客户端传输数据**********************/
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
if(name.equals("hu")&&pwd.equals("123")) {
dos.writeUTF("登录成功");
}
else {
dos.writeUTF("登录失败");
}
dis.close();
socket.close();
serve.close();
}
}
客户端
package io.github.tcp;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client3 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("---------Client-------------");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入姓名:");
String name=br.readLine();
System.out.println("密码:");
String pwd=br.readLine();
Socket socket=new Socket("localhost",9999);
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
String str="name="+name+"&"+"pwd="+pwd;
dos.writeUTF(str);
/*******************************客户端接收信息*************************/
DataInputStream dis=new DataInputStream(socket.getInputStream());
String str2=dis.readUTF();
System.out.println(str2);
dos.close();
socket.close();
}
}
文件传输
服务端
package io.github.tcp;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileServe {
public static void main(String[] args) throws IOException {
System.out.println("--------Serve----------");
ServerSocket serve=new ServerSocket(9999);
Socket socket=serve.accept();
DataInputStream dis=new DataInputStream(socket.getInputStream());
OutputStream os=new BufferedOutputStream(new FileOutputStream(new File("copy.jpg")));
int len=-1;
byte[] b=new byte[1024];
while((len=dis.read(b))!=-1) {
os.write(b, 0, len);
os.flush();
}
os.close();
dis.close();
socket.close();
serve.close();
}
}
客户端
package io.github.tcp;
import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class FileClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("---------Client-------------");
Socket client=new Socket("localhost",9999);
InputStream is=new BufferedInputStream(new FileInputStream("src/myGirl.jpg"));
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
int len=-1;
byte[] b=new byte[1024];
while((len=is.read(b))!=-1) {
dos.write(b, 0, len);
dos.flush();
}
dos.close();
is.close();
client.close();
}
}
一个服务端有多个客户端访问链接
使用多线程可以多用户同时访问,减少客户端访问的等待时间。
```package io.github.tcp;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Serve3 {
static class Channl implements Runnable{
private Socket socket;
private DataInputStream dis;
private DataOutputStream dos;
private String[] datas;
private String name;
private String pwd;
public Channl(Socket socket) {
this.socket=socket;
//this.serve=serve;
try {
this.dis=new DataInputStream(socket.getInputStream());
this.dos=new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String str;
try {
str = dis.readUTF();
datas=str.split("&");
} catch (IOException e) {
e.printStackTrace();
}
for(String info:datas) {
String[] values=info.split("=");
if(values[0].equals("name")) {
System.out.println("用户名为:"+values[1]);
name=values[1];
}
else if(values[0].equals("pwd")) {
System.out.println("密码为:"+values[1]);
pwd=values[1];
}
}
if(name.equals("hu")&&pwd.equals("123")) {
try {
dos.writeUTF("登录成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
try {
dos.writeUTF("登录失败");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
System.out.println("--------Serve----------");
ServerSocket serve=new ServerSocket(9999);
while(true) {
Socket socket=serve.accept();
System.out.println("一个客户端建立链接");
new Thread(new Channl(socket)).start();
}
}
}