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("校验失败");
}
}
}