下面的案例是C/S结构,既编写客户端有编写服务端而且没有用到http协议

对于B/S结构,我们只需要编写服务器,不需要写客户端。

服务端和单客户端通信

注意事项:如果服务端或者客户端采用read() 一个字节这种读取数据,只要另一方没有关闭连接,read是永远读取不到-1,会陷入死循环中;

解决方法:加上一个判断,程序员自己跳出循环,比如在while循环中,加上

if(strbuilder.indexOf("\n") > 0){//存在消息结束标志

break;

}

服务端代码

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

public class Server {

public static void main(String[] args) {

try {

ServerSocket server = new ServerSocket(8080);

Socket socket = server.accept();

System.out.println("客户端连接成功:"+server.getInetAddress().getHostAddress());

BufferedReader bufRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));

String s = bufRead.readLine();

System.out.println("message="+s);

BufferedWriter bufwrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

bufwrite.write("你好我是服务端\n");

bufwrite.flush();

bufwrite.close();

bufRead.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

客户端代码

import java.io.*;

import java.net.Socket;

public class client {

public static void main(String[] args) {

try {

Socket socket = new Socket("127.0.0.1",8080);

BufferedWriter bufWrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

//如果服务器使用readline来读取数据,那么发送的数据后面必须加上\n;

bufWrite.write("你好我是客户端\n");

bufWrite.flush();

//PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));

//ps.println("dddd");

//ps.flush();

BufferedReader bufread = new BufferedReader(new InputStreamReader(socket.getInputStream()));

System.out.println(bufread.readLine());

//ps.close();

bufWrite.close();

bufread.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

服务器和多客户端通信

即采用多线程的方式进行处理任务

服务端

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class Server {

public static void main(String[] args) {

try {

ExecutorService es = Executors.newFixedThreadPool(4);

ServerSocket server = new ServerSocket(8080);

while (true){

Socket socket = server.accept();

System.out.println("有客户端连接");

es.execute(new ServerHandle(socket));

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ServerHandle implements Runnable{

private Socket socket;

public ServerHandle(Socket socker){

this.socket = socker;

}

@Override

public void run() {

BufferedReader bufRead = null;

try {

bufRead = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));

char[] chars = new char[1024];

StringBuilder strbuilder = new StringBuilder();

int len=-1;

while ((len=bufRead.read(chars))!=-1){

strbuilder.append(new String(chars),0,len);

if(strbuilder.indexOf("\n") > 0){//存在消息结束标志

break;

}

}

System.out.println("message="+ strbuilder);

BufferedWriter bufwrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

bufwrite.write("已经收到你的信息:"+strbuilder+"\n");

bufwrite.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

}

客户端

import java.io.*;

import java.net.Socket;

import java.util.Scanner;

public class client {

public static void main(String[] args) {

try {

Socket socket = new Socket("127.0.0.1",8080);

BufferedWriter bufWrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

//如果服务器使用readline来读取数据,那么发送的数据后面必须加上\n;

Scanner input = new Scanner(System.in);

System.out.println("输入一个发送的信息");

String x = input.next();

bufWrite.write(x+"\n");

bufWrite.flush();

BufferedReader bufread = new BufferedReader(new InputStreamReader(socket.getInputStream()));

System.out.println(bufread.readLine());

bufWrite.close();

bufread.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

多客户端之间的通信

Server端

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Vector;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class Server {

public static void main(String[] args) {

//保存所有的处理 用户请求连接的 线程

Vector vector = new Vector<>();

ExecutorService es = Executors.newFixedThreadPool(4);

try {

ServerSocket server = new ServerSocket(8080);

System.out.println("服务器已经启动.......");

while (true){

Socket socket = server.accept();

UserRequestHandle user = new UserRequestHandle(socket,vector);

vector.add(user);

es.execute(user);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class UserRequestHandle implements Runnable{

private String name;//客户端的名字(唯一),可以绑定用户对象(唯一);

private ObjectInputStream ois;

private ObjectOutputStream oos;

private Socket socket;

private Boolean flag=true;

private Vector verctor;

public UserRequestHandle(Socket socket,Vector verctor){

this.socket = socket;

this.verctor = verctor;

}

@Override

public void run() {

try {

ois = new ObjectInputStream(socket.getInputStream());

oos = new ObjectOutputStream(socket.getOutputStream());

while (flag){

Message message = (Message) ois.readObject();

int mes = message.getType();

switch (mes){

case MessageType.type_login:{

name = message.getFrom(); //表示给当前的线程取一个名字;

message.setMessage("欢迎登录"+message.getFrom());

oos.writeObject(message);

break;

}

case MessageType.type_send:{

String to_user = message.getTo();

String to_user_message = message.getMessage();

for (int i = 0; i < verctor.size(); i++) {

if (verctor.get(i).name==null|to_user==null){

continue;

}

if (verctor.get(i).name.equals(to_user)&&!to_user.equals(this.name)){

System.out.println("消息已经正在发送给对方.....");

message.setFrom(name);

message.setMessage(to_user_message);

verctor.get(i).oos.writeObject(message);

break;

}

}

}

}

}

ois.close();

oos.close();

} catch (IOException|ClassNotFoundException e) {

e.printStackTrace();

return;

}catch (Exception e){

}

}

}

客户端

import java.io.*;

import java.net.Socket;

import java.util.Scanner;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class client {

public static void main(String[] args) {

Scanner input = new Scanner(System.in);

try {

Socket socket = new Socket("127.0.0.1",8080);

System.out.println("连接服务器成功......");

ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

//第一步先登录;

System.out.println(MessageType.type_login+","+MessageType.type_send);

System.out.println("输入用户名");

String name = input.next();

oos.writeObject(new Message(name,null,MessageType.type_login,null));

Message message = (Message) ois.readObject();

System.out.println(message.getMessage());

//创建一个单线程从socket中循环取出消息(只读)

ExecutorService receve_message = Executors.newSingleThreadExecutor();

receve_message.execute(new ReceveMessage(ois));

//不断给服务发送消息(只写)

while (true){

System.out.println("输入要发送消息的用户名");

String to_user = input.next();

System.out.println("输入消息");

String to_user_message = input.next();

oos.writeObject(new Message(name,to_user,MessageType.type_send,to_user_message));

}

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

class ReceveMessage implements Runnable{

private ObjectInputStream ois;

public ReceveMessage(ObjectInputStream ois){

this.ois = ois;

}

@Override

public void run() {

try {

while (true){

Message message = (Message) this.ois.readObject();

System.out.println("["+message.getFrom()+"]"+":"+message.getMessage());

}

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

message信息对象

import java.io.Serializable;

public class Message implements Serializable {

private String from; //发送消息的人(以后可以用ip来处理)

private String to; //发送消息给谁(以后可以用ip来处理)

private int type; //int type 消息的类型(是登录还是进行消息的发送)

private String message;//消息的内容

public Message(String from, String to, int type, String message) {

this.from = from;

this.to = to;

this.type = type;

this.message = message;

}

public String getFrom() {

return from;

}

public String getTo() {

return to;

}

public int getType() {

return type;

}

public String getMessage() {

return message;

}

public void setFrom(String from) {

this.from = from;

}

public void setTo(String to) {

this.to = to;

}

public void setMessage(String message) {

this.message = message;

}

}

MessageType表示配置文件

public class MessageType {

public static final int type_login = 1;//消系中有type_login表示需要登录

public static final int type_send = 2; //消息中有type_send表示该消息为发送

}

TCP聊天室原理

服务器用于转发消息

客户端和服务器建立一个socket连接

客户端将socker交给两个线程处理,一个线程(可以使用主线程)用来接收服务端的数据,一个线程用来发送数据

服务端接收到一个连接请求,就开启1个线程来处理请求,并将socker添加到列表中这个列表可以被每一个线程共享,当线程接收到数据后,就遍历列表,对每一个socker进行发送数据(可以选择不给自己发送数据,!=this)。

TCP私聊

我们之前已经封装好了一个socker列表,当某一个客户端发送数据@xx:你好,我们可以截取xx,在发送数据的时候如果数据中有@符号,就给某一个socker发送数据。

注意我们可以封装一个socker连接对象,里面传入socker,name,并且封装send(),recive()方法,将这个封装对象add到列表中。

UDP服务端和客户端通信

UDP没有严格意义上的服务端

服务端

public class Server {

public static void main(String[] args) throws IOException {

//UDP协议要求包小于64K,我们用500个字节数组来接受数据,如果发送的数据大于500个字节,超过500字节的数据接受不到

byte[] bs = new byte[500];

//准备容器,用这个容器来接受客户端发送的数据

DatagramPacket p1 = new DatagramPacket(bs, bs.length);

//创建数据报套接字

DatagramSocket socket_B = new DatagramSocket(10010);

//接收数据报包

socket_B.receive(p1);

System.out.println(new String(bs, 0, p1.getLength()));

byte[] send_msg = "我是服务端,我已经收到你的消息".getBytes();

InetAddress desIp = p1.getAddress(); //获取对方的ip

int dedport = p1.getPort();

//数据包中包括数据,数据长度,对方的ip和绑定的端口

DatagramPacket p = new DatagramPacket(send_msg, send_msg.length, desIp, dedport);

socket_B.send(p);

socket_B.close();

}

}

客户端

public class Client {

public static void main(String[] args) throws IOException {

byte[] send_bs = "我是客户端,我给你发送了一些数据".getBytes();//要发的信息内容

//创建数据报,里面包括 数据和数据长度 对方的ip地址 和 对方的端口,

DatagramPacket p1 = new DatagramPacket(send_bs, send_bs.length, InetAddress.getByName("127.0.0.1"),10010);

//创建数据报套接字,绑定端口

DatagramSocket socket = new DatagramSocket(8080);

socket.send(p1);

//用数组接收数据报包

byte[] rece_msg = new byte[500];

DatagramPacket p = new DatagramPacket(rece_msg, rece_msg.length);

socket.receive(p);//数据量如果多,可以使用while循环

System.out.println(new String(rece_msg, 0, p.getLength()));

//关闭套接字

socket.close();

}

}

udp实现双向发送数据

服务端(客户端)和客户端都必须开2个线程,一个线程用于发送数据,System.in堵塞该线程,一个线程等待对方发送数据,receive()堵塞该线程

一个简单的B/S架构服务器

http协议(应用层传输协议)

首先tcp/udp协议,只能保证数据的发送,服务器(客户端)通过tcp可以获取客户端(服务器)发送的消息,但是如果来解析这些数据呢,这就需要一个标准的协议,并且全世界都必须遵循。这个协议(http),规定了服务器和客户端发送数据的格式。接受方有安装标准协议来解析这些数据,获得有用的信息。

现在浏览器会安装http协议通过tcp发送一段特殊的格式的数据,你的服务器就需要按照http协议的格式来解析这些数据,而服务器发送给浏览器的数据,浏览器只会按照http标准格式数据解析。所以我们发送的数据必须按照http格式要求写。

当然如果你可以单独开发一款浏览器,这个浏览器访问你的服务器,你想怎么定协议就怎么定协议。只要你的服务器和浏览器可以解析正确的数据就行,你也可以将你解析数据的方式,和方式数据的格式定义你的协议。这就是应用层协议。

请求协议

请求行:方法(GET/POST)、URI、协议/版本

请求头:Request Header

请求正文

1、请求行

GET /index.htm1?name=xx HTTP/1.1

2、请求体

Accept:text/html,application/xhtml+xml,*/*

Accept-Language:zh-CN

User-Agent:Mozilla/5.0(compatible;MSIE 9.0;W indows NT 6.1;Trident/5.0)

Accept-Encoding:ggip,deflate

Host:localhost

Connection:Keep-Alive

3、请求正文

响应协议

状态行:协议/版本、状态码,转态描述

响应头(Response Header)

响应正文

1、状态行

HTTP/1.0 2000K

2、请求头:

Date:Mon,31Dec209904:25:57GMT

Server:shsxt Server/0.0.1;charset=GBK

Content-type:text/html

Content-length:397254263

请求正文(注意与请求头之间有个空行)

xxxx

服务器

public class Server {

public static void main(String[] args) {

try {

ServerSocket server = new ServerSocket(8080);

Socket socket = server.accept();

System.out.println("客户端连接成功:"+server.getInetAddress().getHostAddress());

BufferedReader bufRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));

String s = bufRead.readLine();

System.out.println("message="+s);

BufferedWriter bufwrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

bufwrite.write("HTTP 1.1\r\n\r\n

xx

");

bufwrite.flush();

bufwrite.close();

bufRead.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

dup java_java web----TCP/DUP 通信相关推荐

  1. dup java_java虚拟机指令dup详解

    本文实例为大家介绍了java虚拟机指令dup,供大家参考,具体内容如下 举个例子: public class ExceptionTest{ void cantBeZero(int i) throws ...

  2. TCP报文( tcp dup ack 、TCP Retransmission)

    最近因使用FTP 上传数据的时候总是不能成功,抓包后发现 TCP 报文出现 TCP dup ack 与 TCP Retransmission 两种类型的包.收集整理下 TCP dup ack (重复应 ...

  3. 《Linux高性能服务器编程》学习总结(四)——TCP/IP通信案例:访问Internet上的Web服务器...

    第四章      TCP/IP通信案例:访问Internet上的Web服务器 HTTP协议是工作在应用层上的协议,其应用十分广泛,而在进行通信的过程中,经常使用HTTP代理服务器.HTTP代理服务器主 ...

  4. 关于抓包出现TCP DUP ACK问题

    最近在跟一个CDN服务器端做对接,从CDN服务器下载内容(http),发现抓包出现非常多的Tcp Dup Ac​k异常提示.通过查阅质料得知Tcp Dup Ack xxx#y 代表了数据段丢失TCP状 ...

  5. TCP Dup ACK xxx#x分析

    TCP Dup ACK xxx#x分析 wireshark报文出现TCP Dup ACK xxx#x时,代表了数据段丢失 TCP 状态,xxx 代表数据丢失的位置(即wireshark报文显示界面最左 ...

  6. TCP报文之-tcp dup ack 、tcp Out-of-Order

    使用WireShark抓包,选择TCP报文,TCP是一种安全的协议,在网络出现状况时也能安全稳定的传输数据,但是在网络出现问题时tcp报文中会有很多中情况导致报文重传或者是重组.现在就在报文中遇到的几 ...

  7. WebSocket 实现 Web 端即时通信

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了~ 前言 WebSocket 是HTML5开始提 ...

  8. asp.core api 通过socket和服务器通信发送udp_【网络通信】TCP的通信过程

    本文主要介绍以下几个内容: 1.TCP.UDP.Socket分别是什么?有什么区别? 2.TCP的基本过程. 3.TCP三次握手建立连接. 4.TCP四次挥手断开连接. 5.常考查其他问题. 1.TC ...

  9. 51单片机 ENC28J60 TCP/IP通信

    51单片机 ENC28J60 TCP/IP通信 单片机:STC90C516RD+ ENC28J60模块:mini(3.3V供电) 设备:PC.开发板.两个网线.路由器 首先先介绍一下本文的移植针对于单 ...

  10. java tcp read_【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)...

    书上示例 在第一章<基本套接字>中,作者给出了一个TCP Socket通信的例子--反馈服务器,即服务器端直接把从客户端接收到的数据原原本本地反馈回去. 书上客户端代码如下: 书上的服务器 ...

最新文章

  1. Shoot the Bullet(ZOJ3229)(有源汇上下界最大流)
  2. LeetCode——Longest Substring Without Repeating Characters
  3. 文巾解题 185. 部门工资前三高的所有员工
  4. 解决Windows客户端访问vsftpd服务器中文乱码问题
  5. 十万个为什么之为什么大家都说dubbo
  6. 关于Java单例模式中懒汉式和饿汉式的两种类创建方法
  7. IDEA快捷键拆解系列(七):Analyze篇
  8. N皇后问题(回溯算法解法)
  9. getwmi php 报错,调用win32_service类就报错“get-wmiobject :常规故障”,这是wmi类损坏?...
  10. VC2005字符集设置容易出错的问题!
  11. 3.7V锂电池升压到5V1A,FS2114升压转换芯片设计布局
  12. VS 2015社区版离线下载
  13. 多副本和raid技术
  14. Win11磁盘被写保护怎么办?Win11磁盘被写保护解除方法
  15. 计算机应用 2010 成绩,2010西电计算机应用技术考研成绩
  16. uniapp app 端打开pdf文件方式
  17. Android开发神器总结
  18. Miracast协议
  19. 了解什么是架构基本概念和架构本质
  20. LVGL学习——初识动画 lv_anim_t

热门文章

  1. 敏捷图书排行 (2011年修订)【转】
  2. 【原】让两个DIV高度一样的Javascript函数
  3. 初学者python笔记(内置函数_1)
  4. oracle union all 特别慢_值得收藏的Oracle数据库性能优化
  5. Python+socket实现TCP套接字服务端自由限速
  6. 微课|玩转Python轻松过二级(2.4节):常用内置函数用法精要4
  7. Python函数式编程小案例:文本加密
  8. PHP三年15K,程序员月薪15K相亲三年才成功,被拒理由:这个薪资提鞋都嫌弃
  9. java画圈_java动态画圈圈。运用多线程,绘图
  10. 帝国cms 留言板html,帝国CMS留言板加字段和验证码