1.什么是TCP,它的优缺点是什么?
TCP--传输控制协议[有连接的协议]
优点:保证数据安全可靠
缺点:消耗大,效率低
2..建立基于TCP的网络通讯程序需要使用的类和常用方法?
基于TCP的网络通讯程序是区分客户端和服务器端
创建客户端程序
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() 关闭此套接字。 |
创建服务器端程序
1.java.net Class ServerSocket 创建基于TCP的通讯程序的服务器端对象的java类
通过这个类创建的对象就表示一个服务器端
2.构造方法
SeverSocket(int port) 创建绑定到指定端口的服务器套接字。
3.实例方法
Socket | accept() 侦听要连接到此套接字并接受它。 【阻塞主线程运行】 | |
void | close() 关闭此套接字。 |
例如:完成客户端向服务器送数据,服务器接收到客户端发送来的数据。
客户端向服务器送数据
//发送一次数据就会结束,不能连续发送
package com.wangxing.test1;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* 基于TPC的客户端【发送数据】
* @author feng
*
*/
public class TestClient1 {
public static void main(String[] args) throws Exception {
//定义服务器端的IP
//获得封装有本机IP地址的InetAddress对象
InetAddress serverIP=InetAddress.getLocalHost();
//定义服务端的port
int serverport=3000;
//创建客户端对象
Socket client=new Socket(serverIP,serverport);
Scanner input=new Scanner(System.in);
System.out.println("请输入需要发送的数据:");
String info=input.nextLine();
//要将数据从客户端发送到服务器端,需要用输出流发送
//得到输出流
OutputStream out=client.getOutputStream();
//写出数据
out.write(info.getBytes());
//关闭流
out.close();
//关闭Socket
client.close();
}
}
服务器接收到客户端发送来的数据
//接收一次数据就会结束,不能连续接收
package com.wangxing.test1;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 基于TCP的服务器【接受数据】
* @author feng
*
*/
public class TestServer {
public static void main(String[] args) throws Exception {
//指定服务器开启的端口
int serverport=3000;
//创建服务器端对象
ServerSocket server1=new ServerSocket(serverport);
System.out.println("服务器准备完毕,等待客户端连接......");
//获取连接的客户端
Socket client1=server1.accept();
//通过连接进入的客户端对象得到输入流,以接收客户端发送来的数据
InputStream in=client1.getInputStream();
//创建保存发送来的数据用的字节数组
byte data[]=new byte[1024];//不知道具体大小,所以设置1kb做限制,一次只能发送1kb的数据
//读取客户端发送来的数据
int len=in.read(data);
//将保存在字节数组中的数据转换成String
String msg=new String(data,0,len);
System.out.println("接受客户端发送来的数据是:"+msg);
//关闭流
in.close();
//关闭Socket
client1.close();
//关闭ServerSocket
server1.close();
}
}
例如1:完成客户端持续向服务器送数据,服务器持续接收到客户端发送来的数据。
客户端持续向服务器送数据
//持续发送消息给服务器
package com.wangxing.test2;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* 基于TPC的客户端【发送数据】
* @author feng
*
*/
public class TestClient2 {
public static void main(String[] args)throws Exception {
//定义服务器端的IP
InetAddress serverIP=InetAddress.getLocalHost();
//定义服务器端连接的端口
int serverpost=3000;
//创建客户端对象
Socket client=new Socket(serverIP,serverpost);
//用客户端对象的实例方法获得输出流
OutputStream out=client.getOutputStream();
//定义控制持续发送的变量
boolean flag=true;
//定义Scanner对象
Scanner input=new Scanner(System.in);
//循环是为了控制持续发送消息
while(flag){
System.out.println("请输入将要发送的数据");
String info=input.nextLine();
//写出数据(向服务器端发送数据)
out.write(info.getBytes());
//根据输入的数据判断是否关闭客户端
if(info.equals("exit")){
System.out.println("客户端关闭");
flag=false;
}
}
//关闭流
out.close();
//关闭客户端Socket
client.close();
}
}
服务器持续接收到客户端发送来的数据
//持续接收客户端发送过来的数据
package com.wangxing.test2;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 基于TCP的服务器【接受数据】
* @author feng
*
*/
public class TestServer2 {
public static void main(String[] args) throws Exception{
//定义服务器接收数据的端口
int serverpost=3000;
//创建服务器端对象
ServerSocket server1=new ServerSocket(serverpost);
System.out.println("服务器准备完毕,等待客户端连接......");
//通过服务器端对象的accept()方法获取连接的客户端对象
Socket client1=server1.accept();
//通过客户端对象的实例方法获得输入流,以接收客户端发送过来的数据
InputStream in=client1.getInputStream();
//创建接收数据的字节数组
byte data[]=new byte[1024];
//定义控制持续接收的变量
boolean flag=true;
while(flag){
int len=in.read(data);
String msg=new String(data,0,len);
System.out.println("接收到客户端发送来的数据是:"+msg);
if(msg.equals("exit")){
flag=false;
}
}
}
}
例如2:完成客户端持续向服务器送数据,还能接收服务器返回的信息,服务器持续接收到客户端发送来的数
据,还可以向客户端返回信息。客户端持续向服务器送数据,还能接收服务器返回的信息。
package com.wangxing.test3;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* 基于TPC的客户端【发送数据】
* @author feng
*
*/
public class TestClient3 {
public static void main(String[] args)throws Exception {
//定义服务器端IP
InetAddress serverIP=InetAddress.getLocalHost();
//定义服务器端接收数据的端口
int serverpost=2500;
//创建客户端对象
Socket client1=new Socket(serverIP,serverpost);
//得到输出流 给服务器端发送数据
OutputStream out=client1.getOutputStream();
//得到输入流 接收服务器端返回来的信息
InputStream in=client1.getInputStream();
//定义一个字节数组接收服务器返回的消息
byte data[]=new byte[1024];
//定义控制持续发送数据的变量
boolean flag=true;
//创建Scanner对象
Scanner input=new Scanner(System.in);
//控制持续发送
while(flag){
System.out.println("请输入要发送的数据");
String info=input.nextLine();
//写出数据
out.write(info.getBytes());
//根据输入的数据判断是否关闭客户端
if(info.equals("exit")){
System.out.println("客户端关闭");
flag=false;
}else{
//开始接收服务器返回的数据
int len=in.read(data);
//将保存在字节数组中的数据转换成String
String msg=new String(data,0,len);
System.out.println("接收来自服务器端的数据是:"+msg);
}
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//关闭客户端
client1.close();
}
}
服务器持续接收到客户端发送来的数据,还可以向客户端返回信息
package com.wangxing.test3;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 基于TCP的服务器【接受数据】
* @author feng
*
*/
public class TestServer3 {
public static void main(String[] args)throws Exception {
//指定服务器开启的端口
int serverpost=2500;
//创建服务器端对象
ServerSocket server1=new ServerSocket(serverpost);
System.out.println("服务器端已准备就绪,等待客户端连接......");
//通过服务器端对象的accept()方法获取连接服务器的客户端对象
Socket client1=server1.accept();
//得到输入流 接收客户端发送的数据
InputStream in=client1.getInputStream();
//得到输出流, 向客户端返回数据
OutputStream out=client1.getOutputStream();
//创建保存客户端发送过来的数据的字节数组
byte data[]=new byte[1024];
//定义控制连续接收数据的变量
boolean flag=true;
//控制连续接收数据
while(flag){
//读取客户端发送来的数据
int len=in.read(data);
//将保存在字节数组中的数据转换成String
String msg=new String(data,0,len);
System.out.println("接收来自客户端的数据是:"+msg);
if(msg.equals("exit")){
System.out.println();
flag=false;
}else{
//开始向客户端返回数据
msg="server"+msg;
out.write(msg.getBytes());
}
}
//关闭输出流
out.close();
//关闭输入流
in.close();
//关闭客户端
client1.close();
//关闭服务器端
server1.close();
}
}
例如3:多客户端,配置一台服务器,独立运行
package com.wangxing.test4;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* 基于TCP的客户端【持续发送数据】
* @author feng
*
*/
public class TestClient4 {
public static void main(String[] args) throws Exception{
//定义服务器端的IP
InetAddress serverIP=InetAddress.getLocalHost();
//定义服务器端连接的端口
int serverpost=3500;
//创建客户端对象
Socket client1=new Socket(serverIP,serverpost);
//得到输出流 向服务器端发送数据
OutputStream out=client1.getOutputStream();
//得到输入流 接收服务器端返回来的数据
InputStream in=client1.getInputStream();
//创建一个保存服务器端返回数据的字节数组
byte data[]=new byte[1024];
//定义一个控制持续发送的变量
boolean flag=true;
//创建一个Scanner对象
Scanner input=new Scanner(System.in);
//控制持续发送数据
while(flag){
System.out.println("请输入你要发送的数据");
String info=input.nextLine();
out.write(info.getBytes());
if(info.equals("exit")){
System.out.println("客户端关闭");
flag=false;
}else{
int len=in.read(data);
String msg=new String(data,0,len);
System.out.println("接收服务器端传来的数据是:"+msg);
}
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//关闭客户端
client1.close();
}
}
服务器为连接到服务器的每一个客户端构造的线程类
package com.wangxing.test4;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* 客户端线程类
* @author feng
*
*/
public class ClientThread implements Runnable {
private Socket client;
private InputStream in;
private OutputStream out;
private boolean flag=true;
public ClientThread(Socket client){
this.client=client;
}
//完成读写数据的操作
@Override
public void run() {
try{
//创建读写数据用户的输入输出流对象
in=client.getInputStream();
out=client.getOutputStream();
//定义保存读出数据的字节数组
byte data[]=new byte[1024];
while(flag){
//读取数据到字节数组
int len=in.read(data);
//将读取来保存在字节数组中的数据转换成String
String msg=new String(data,0,len);
System.out.println("读取的数据是:"+msg);
//判断退出
if(msg.equals("exit")){
System.out.println("客户端从服务器端退出");
flag=false;
}else{
msg="server-"+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;
/**
* 基于TCP的服务器【接收数据】
* @author feng
*
*/
public class TestServer4 {
public static void main(String[] args)throws Exception {
//指定一个服务器开启的接口
int serverpost=3500;
//创建一个服务器端对象
ServerSocket server1=new ServerSocket(serverpost);
System.out.println("服务器已准备就绪,等待客户端连接........");
//定义控制接收客户端的变量
boolean flag=true;
//因为一个服务器端要连接很多客户端,所以这里要循环
while(flag){
//通过服务器对象的accept()方法获得已连接服务器的客户端对象
Socket client=server1.accept();
//目标对象
ClientThread clientthread=new ClientThread(client);
//线程对象
Thread thread=new Thread(clientthread);
thread.start();
}
server1.close();
}
}
总结:
客户端程序的开发步骤:
1.创建客户端对象【Socket】,连接服务器
2.通过客户端对象【Socket】的getInputStream() / getOutputStream(),得到输入输出流
3.通过得到的输入输出流对象调用read()/write()方法完成数据收发。
4.关闭输入输出流和客户端对象【Socket】。
服务器端程序的开发步骤:
1.创建服务器端对象【ServerSocket】,开启服务器
2.通过服务器端对象【ServerSocket】的accept()方法,获得连接进入服务器的客户端对象【Socket】
3.连接进入服务器的客户端对象【Socket】的getInputStream() / getOutputStream(),得到输入输出流.
4.通过得到的输入输出流对象调用read()/write()方法完成数据收发。
5.关闭输入输出流和客户端对象【Socket】以及服务器端对象【ServerSocket】。