一、什么是TCP,他的优缺点是什么
TCP —> 传输控制协议
优点:保证数据安全可靠
缺点:消耗大、效率低
二、建立基于TCP的网络通讯程序需要使用的类和常用方法
基于TCP的网络通讯程序是区分客户端和服务器端
2.1 创建客户端程序
1. java.net Class Socket 创建基于TCP的通讯程序的客户端对象的java类
通过这个类创建的对象就表示一个客户端
2. 构造方法
Socket(InetAddress address, int port) | 创建流套接字并将其连接到指定IP地址的指定端口号 |
---|---|
Socket(String host, int port) | 创建流套接字并将其连接到指定主机上的指定端口号 |
3. 常用实例方法
OutputStream | getOutputStream() 返回此套接字的输出流 |
---|---|
InputStream | getInputStream() 返回此套接字的输入流 |
void | close() 关闭此套接字 |
2.2创建服务器端程序
1. java.net Class ServerSocket 创建基于TCP的通讯程序的服务器端对象的java类
通过这个类创建的对象就表示一个服务器端
2. 构造方法
ServerSocket(int port) | 创建绑定到指定端口的服务器套接字 |
---|
3. 常用实例方法
Socket | accept() 侦听要连接到此套接字并接受它。 【阻塞主线程运行】 |
---|---|
void | close() 关闭此套接字 |
例如1:完成客户端向服务器发送数据,服务器接收到客户端发送过来的数据
客户端向服务器发送数据
package com.wangxing.test1;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端
public class TcpClient1 {
public static void main(String[] args) throws Exception{
//定义保存服务器端ip地址的对象
//String serverip="";
InetAddress serverip=null;
//定义保存服务器端端口号的变量
int serverport=3000;
//定义连接服务器的客户端对象
Socket client=null;
//定义接收控制台信息的输入流
BufferedReader inputinfo=null;
//定义保存被发送数据的字符串变量
String info=null;
//定义发送数据的输出流对象
OutputStream out=null;
//实例化保存服务器ip地址的对象
serverip=InetAddress.getLocalHost();
//实例化客户端对象,连接到服务器
client=new Socket(serverip,serverport);
//实例化接收控制台信息的输入流
inputinfo=new BufferedReader(new InputStreamReader(System.in));
//提醒用户请输入被发送的信息
System.out.println("请输入被发送的信息:");
//接收被发送的信息
info=inputinfo.readLine();
//创建发送数据的输出流对象
out=client.getOutputStream();
//将被发送的数据写出
out.write(info.getBytes());
//关闭流和客户端
out.close();
inputinfo.close();
client.close();
}
}
服务器接收到客户端发送来的数据
package com.wangxing.test1;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务器端
public class TcpServer1 {
public static void main(String[] args)throws Exception {
//定义服务器需要开发的端口号
int prot=3000;
//定义服务器端对象
ServerSocket server=null;
//定义保存连接到服务器的客户端对象
Socket client=null;
//定义读取客户端发送来的数据的输入流对象
InputStream in=null;
//定义保存客户端发送来的数据的字符串变量
String msg=null;
//实例化服务器对象
server=new ServerSocket(prot);
System.out.println("服务器已经开启,等待客户端连接......");
//服务器得到连接进来的客户端对象
client=server.accept();
//实例化读取客户端发送来的数据的输入流对象
in=client.getInputStream();
//读取客户端信息
byte data[]=new byte[100];
int len=in.read(data);
//将读取到字节数组中的数据转换成字符串
msg=new String(data,0,len);
System.out.println("服务收到来自客户端的信息=="+msg);
//关闭流和客户端以及服务器
in.close();
client.close();
server.close();
}
}
运行结果:
例如2:完成客户端持续向服务器送数据,服务器持续接收到客户端发送来的数据。
客户端持续向服务器送数据
package com.wangxing.test2;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端
public class TcpClient1 {
public static void main(String[] args) throws Exception{
//定义保存服务器端ip地址的对象
//String serverip="";
InetAddress serverip=null;
//定义保存服务器端端口号的变量
int serverport=3000;
//定义连接服务器的客户端对象
Socket client=null;
//定义接收控制台信息的输入流
BufferedReader inputinfo=null;
//定义保存被发送数据的字符串变量
String info=null;
//定义发送数据的输出流对象
OutputStream out=null;
//定义控制持续发送数据的boolean变量
boolean flag=true;
//实例化保存服务器ip地址的对象
serverip=InetAddress.getLocalHost();
//实例化客户端对象,连接到服务器
client=new Socket(serverip,serverport);
//实例化接收控制台信息的输入流
inputinfo=new BufferedReader(new InputStreamReader(System.in));
//创建发送数据的输出流对象
out=client.getOutputStream();
//持续发送数据
while(flag) {
//提醒用户请输入被发送的信息
System.out.println("请输入被发送的信息:");
//接收被发送的信息
info=inputinfo.readLine();
//将被发送的数据写出
out.write(info.getBytes());
//判断退出客户端
if(info.equals("886")) {
flag=false;
}
}
//关闭流和客户端
out.close();
inputinfo.close();
client.close();
}
}
服务器持续接收到客户端发送来的数据
package com.wangxing.test2;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer1 {
public static void main(String[] args)throws Exception {
//定义服务器需要开发的端口号
int prot=3000;
//定义服务器端对象
ServerSocket server=null;
//定义保存连接到服务器的客户端对象
Socket client=null;
//定义读取客户端发送来的数据的输入流对象
InputStream in=null;
//定义保存客户端发送来的数据的字符串变量
String msg=null;
//定义保存控制持续接收数据的boolena变量
boolean flag=true;
//实例化服务器对象
server=new ServerSocket(prot);
System.out.println("服务器已经开启,等待客户端连接......");
//服务器得到连接进来的客户端对象
client=server.accept();
//实例化读取客户端发送来的数据的输入流对象
in=client.getInputStream();
//控制持续接收数据
while(flag) {
//读取客户端信息
byte data[]=new byte[100];
int len=in.read(data);
//将读取到字节数组中的数据转换成字符串
msg=new String(data,0,len);
System.out.println("服务收到来自客户端的信息=="+msg);
//判断关闭服务器
if(msg.equals("666")) {
flag=false;
}
}
//关闭流和客户端以及服务器
in.close();
client.close();
server.close();
}
}
运行结果:
例如3:完成客户端持续向服务器送数据,还能接收服务器返回的信息,服务器持续接收到客户端发送来的数据,还可以向客户端返回信息。
客户端持续向服务器送数据,还能接收服务器返回的信息
package com.wangxing.test3;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端
public class TcpClient1 {
public static void main(String[] args) throws Exception{
//定义保存服务器端ip地址的对象
//String serverip="";
InetAddress serverip=null;
//定义保存服务器端端口号的变量
int serverport=3000;
//定义连接服务器的客户端对象
Socket client=null;
//定义接收控制台信息的输入流
BufferedReader inputinfo=null;
//定义保存被发送数据的字符串变量
String info=null;
//定义发送数据的输出流对象
OutputStream out=null;
//定义接收服务器返回信息的输入流对象
InputStream in=null;
//定义保存接收数据的字符串变量
String msg=null;
//定义控制持续发送数据的boolean变量
boolean flag=true;
//实例化保存服务器ip地址的对象
serverip=InetAddress.getLocalHost();
//实例化客户端对象,连接到服务器
client=new Socket(serverip,serverport);
//实例化接收控制台信息的输入流
inputinfo=new BufferedReader(new InputStreamReader(System.in));
//创建发送数据的输出流对象
out=client.getOutputStream();
//创建接收数据的输入流对象
in=client.getInputStream();
//持续发送数据
while(flag) {
//提醒用户请输入被发送的信息
System.out.println("请输入被发送的信息:");
//接收被发送的信息
info=inputinfo.readLine();
//将被发送的数据写出
out.write(info.getBytes());
//判断退出客户端
if(info.equals("666")) {
flag=false;
}
//客户端接收服务器返回的信息
byte data[]=new byte[100];
int len=in.read(data);
msg=new String(data,0,len);
System.out.println("客户端接收到的服务器返回的数据是=="+msg);
}
//关闭流和客户端
in.close();
out.close();
inputinfo.close();
client.close();
}
}
服务器持续接收到客户端发送来的数据,还可以向客户端返回信息
package com.wangxing.test3;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer1 {
public static void main(String[] args)throws Exception {
//定义服务器需要开发的端口号
int prot=3000;
//定义服务器端对象
ServerSocket server=null;
//定义保存连接到服务器的客户端对象
Socket client=null;
//定义读取客户端发送来的数据的输入流对象
InputStream in=null;
//定义返回给客户端发的数据的输出流对象
OutputStream out=null;
//定义保存客户端发送来的数据的字符串变量
String msg=null;
//定义保存控制持续接收数据的boolena变量
boolean flag=true;
//实例化服务器对象
server=new ServerSocket(prot);
System.out.println("服务器已经开启,等待客户端连接......");
//服务器得到连接进来的客户端对象
client=server.accept();
//实例化读取客户端发送来的数据的输入流对象
in=client.getInputStream();
//实例化返回给客户端发的数据的输出流对象
out=client.getOutputStream();
//控制持续接收数据
while(flag) {
//读取客户端信息
byte data[]=new byte[100];
int len=in.read(data);
//将读取到字节数组中的数据转换成字符串
msg=new String(data,0,len);
System.out.println("服务收到来之客户端的信息=="+msg);
//判断关闭服务器
if(msg.equals("666")) {
flag=false;
}
if(msg.equals("吃了吗?")) {
//返回信息给客户端
msg="吃了!";
out.write(msg.getBytes());
}else if(msg.equals("吃的什么?")) {
//返回信息给客户端
msg="油泼面!";
out.write(msg.getBytes());
}else {
msg="不知道!";
out.write(msg.getBytes());
}
}
//关闭流和客户端以及服务器
out.close();
in.close();
client.close();
server.close();
}
}
运行结果:
例如4:多客户端,配置一台服务器,独立运行
package com.wangxing.test4;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端
public class TcpClient1 {
public static void main(String[] args) throws Exception{
//定义保存服务器端ip地址的对象
//String serverip="";
InetAddress serverip=null;
//定义保存服务器端端口号的变量
int serverport=3000;
//定义连接服务器的客户端对象
Socket client=null;
//定义接收控制台信息的输入流
BufferedReader inputinfo=null;
//定义保存被发送数据的字符串变量
String info=null;
//定义发送数据的输出流对象
OutputStream out=null;
//定义接收服务器返回信息的输入流对象
InputStream in=null;
//定义保存接收数据的字符串变量
String msg=null;
//定义控制持续发送数据的boolean变量
boolean flag=true;
//实例化保存服务器ip地址的对象
serverip=InetAddress.getLocalHost();
//实例化客户端对象,连接到服务器
client=new Socket(serverip,serverport);
//实例化接收控制台信息的输入流
inputinfo=new BufferedReader(new InputStreamReader(System.in));
//创建发送数据的输出流对象
out=client.getOutputStream();
//创建接收数据的输入流对象
in=client.getInputStream();
//持续发送数据
while(flag) {
//提醒用户请输入被发送的信息
System.out.println("请输入被发送的信息:");
//接收被发送的信息
info=inputinfo.readLine();
//将被发送的数据写出
out.write(info.getBytes());
//判断退出客户端
if(info.equals("886")) {
flag=false;
}
//客户端接收服务器返回的信息
byte data[]=new byte[100];
int len=in.read(data);
msg=new String(data,0,len);
System.out.println("客户端接收到的服务器返回的数据是=="+msg);
}
//关闭流和客户端
in.close();
out.close();
inputinfo.close();
client.close();
}
}
//服务器为连接到服务器的每一个客户端构造的线程类
package com.wangxing.test4;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ServerThread extends Thread{
//定义保存连接到服务器的客户端对象
private Socket client=null;
//定义读取客户端发送来的数据的输入流对象
private InputStream in=null;
//定义返回给客户端发的数据的输出流对象
private OutputStream out=null;
//定义保存客户端发送来的数据的字符串变量
private String msg=null;
//定义保存控制持续收发信息的boolena变量
private boolean flag=true;
public ServerThread(Socket client) {
this.client=client;
}
@Override
public void run() {
try {
//实例化读取客户端发送来的数据的输入流对象
in=client.getInputStream();
//实例化返回给客户端发的数据的输出流对象
out=client.getOutputStream();
//控制持续接收数据
while(flag) {
//读取客户端信息
byte data[]=new byte[100];
int len=in.read(data);
//将读取到字节数组中的数据转换成字符串
msg=new String(data,0,len);
System.out.println("服务收到来之客户端的信息=="+msg);
//判断关闭服务器
if(msg.equals("666")) {
flag=false;
}
if(msg.equals("吃了吗?")) {
//返回信息给客户端
msg="吃了!";
out.write(msg.getBytes());
}else if(msg.equals("吃的什么?")) {
//返回信息给客户端
msg="油泼面!";
out.write(msg.getBytes());
}else {
msg="不知道!";
out.write(msg.getBytes());
}
}
//关闭流和客户端以及服务器
out.close();
in.close();
client.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
//服务器主程序
package com.wangxing.test4;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer1 {
public static void main(String[] args)throws Exception {
//定义服务器需要开发的端口号
int prot=3000;
//定义服务器端对象
ServerSocket server=null;
//定义保存连接到服务器的客户端对象
Socket client=null;
//定义保存控制持续接收连接到服务器的客户端对象的boolena变量
boolean flag=true;
//实例化服务器对象
server=new ServerSocket(prot);
System.out.println("服务器已经开启,等待客户端连接......");
//持续接收连接到服务的客户端对象
while(flag) {
//服务器得到连接进来的客户端对象
client=server.accept();
//为连接到服务器的客户端开启一条线程
new ServerThread(client).start();
}
server.close();
}
}
三、客户端程序的开发步骤
- 创建客户端对象【Socket】,连接服务器
- 通过客户端对象【Socket】的getInputStream() / getOutputStream(),得到输入输出流
- 通过得到的输入输出流对象调用read()/write()方法完成数据收发。
- 关闭输入输出流和客户端对象【Socket】。
四、服务器端程序的开发步骤
- 创建服务器端对象【ServerSocket】,开启服务器
- 通过服务器端对象【ServerSocket】的accept()方法,获得连接进入服务器的客户端对象【Socket】
- 连接进入服务器的客户端对象【Socket】的getInputStream() / getOutputStream(),得到输入输出流.
- 通过得到的输入输出流对象调用read()/write()方法完成数据收发。
- 关闭输入输出流和客户端对象【Socket】以及服务器端对象【ServerSocket】。