1. 创建TCP服务端
    1.创建一个ServerSocket对象。
    2.调用accept()方法接收客户端请求。
    3.Socket中获取I/O流。
    4.I/O流进行读写操作,完成与客户端的交互。
    5.关闭I/O流和Socket
  1. import java.io.InputStream;
  2. import java.io.OutputStream;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5.  
  6. public class Server {
  7. public static void main(String[] args) throws Exception {
  8. // 监听指定的端口
  9. int port = 55533;
  10. ServerSocket server = new ServerSocket(port);
  11.  
  12. // server将一直等待连接的到来
  13. System.out.println("server将一直等待连接的到来");
  14. Socket socket = server.accept();
  15. // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
  16. InputStream inputStream = socket.getInputStream();
  17. byte[] bytes = new byte[1024];
  18. int len;
  19. inputStream.read(bytes);
  20. // StringBuilder s = new StringBuilder();
  21. String s=null;
  22. //只有当客户端关闭它的输出流的时候,服务端才能取得结尾的-1
  23. while ((len = inputStream.read(bytes)) != -1) {
  24. // 注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
  25. // s.append(new String(bytes, 0, len, "UTF-8"));
  26. s= new String(bytes, 0, len,"utf-8");
  27. }
  28. System.out.println("server : I get your message : " + s);
  29.  
  30. OutputStream outputStream = socket.getOutputStream();
  31. outputStream.write("this is server ".getBytes("UTF-8"));
  32.  
  33. inputStream.close();
  34. outputStream.close();
  35. socket.close();
  36. server.close();
  37. }
  38. }

创建TCP客户端

1.创建一个Socket对象。

2.从Socket中获取I/O流。

3.对I/O流进行读写操作,完成与服务端的交互。

4.关闭I/O流和Socket

  1. import java.io.InputStream;
  2. import java.io.OutputStream;
  3. import java.net.Socket;
  4.  
  5. public class ClientTest {
  6. public static void main(String args[]) throws Exception {
  7. // 要连接的服务端IP地址和端口
  8. String host = "127.0.0.1";
  9. int port = 55533;
  10. // 与服务端建立连接
  11. Socket socket = new Socket(host, port);
  12. // 建立连接后获得输出流
  13. OutputStream outputStream = socket.getOutputStream();
  14. String message = "client: hello this is client";
  15. socket.getOutputStream().write(message.getBytes("UTF-8"));
  16. //通过shutdownOutput告诉服务器已经发送完数据,后续只能接受数据
  17. socket.shutdownOutput();
  18.  
  19. InputStream inputStream = socket.getInputStream();
  20. byte[] bytes = new byte[1024];
  21. int len;
  22. StringBuilder sb = new StringBuilder();
  23. while ((len = inputStream.read(bytes)) != -1) {
  24. //注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
  25. sb.append(new String(bytes, 0, len,"UTF-8"));
  26. }
  27. System.out.println("client : I get your message " + sb);
  28.  
  29. inputStream.close();
  30. outputStream.close();
  31. socket.close();
  32. }
  33. }

  在传输过程中,客户端需要给服务端发送消息告知自己发送完成,否则服务端会一直等待,直到超时。

1、 此时需要调用方法告诉服务端,自己发送完成。

  1. socket.shutdownOutput(); 而不是 outputStream.close();

如果关闭输出流那模相应的Socket也关闭,相当于  socket.close();

  调用shutdownOutput() ,底层会告知服务端我这边已经写完,服务端知道消息已经读取完,如果服务端有要发送的消息,会发送,如果没有直接关闭socket。

    这样会使得,不能再次发送消息,如果发送需要再次建立连接。在访问频率较高时,将急需优化。

2、通过约定符号

  双方约定一个短语或字符来当做发送完成的标识,比如约定  end 

  1. Socket socket = server.accept();
  2. // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
  3. BufferedReader read=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
  4. String line;
  5. StringBuilder sb = new StringBuilder();
  6. while ((line = read.readLine()) != null && "end".equals(line)) {
  7. //注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
  8. sb.append(line);
  9. }

  优点:不需要关闭流,当发送完一条消息可以再次发送

  缺点:额外的结束标志占带宽,容易误判误被结束,

3、指定长度

  现指定命令长度,然后读取指定长度的内容

  现在首要的问题就是用几个字节指定长度呢,我们可以算一算:

  • 1个字节:最大256,表示256B
  • 2个字节:最大65536,表示64K
  • 3个字节:最大16777216,表示16M
  • 4个字节:最大4294967296,表示4G

   当然我们没必要使用最大长度,而使用边长方式来表示长度:

  • 第一个字节首位为0:即0XXXXXXX,表示长度就一个字节,最大128,表示128B
  • 第一个字节首位为110,那么附带后面一个字节表示长度:即110XXXXX 10XXXXXX,最大2048,表示2K
  • 第一个字节首位为1110,那么附带后面二个字节表示长度:即110XXXXX 10XXXXXX 10XXXXXX,最大131072,表示128K
  • 依次类推
  • 上面提到的这种用法适合高富帅的程序员使用,一般呢,如果用作命名发送,两个字节就够了,如果还不放心4个字节基本就能满足你的所有要求

服务端程序:

  1. import java.io.InputStream;
  2. import java.net.ServerSocket;
  3. import java.net.Socket;
  4.  
  5. public class SocketServer {
  6. public static void main(String[] args) throws Exception {
  7. // 监听指定的端口
  8. int port = 55533;
  9. ServerSocket server = new ServerSocket(port);
  10.  
  11. // server将一直等待连接的到来
  12. System.out.println("server将一直等待连接的到来");
  13. Socket socket = server.accept();
  14. // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
  15. InputStream inputStream = socket.getInputStream();
  16. byte[] bytes;
  17. // 因为可以复用Socket且能判断长度,所以可以一个Socket用到底
  18. while (true) {
  19. // 首先读取两个字节表示的长度
  20. int first = inputStream.read();
  21. //如果读取的值为-1 说明到了流的末尾,Socket已经被关闭了,此时将不能再去读取
  22. if(first==-1){
  23. break;
  24. }
  25. int second = inputStream.read();
  26. int length = (first << 8) + second;
  27. // 然后构造一个指定长的byte数组
  28. bytes = new byte[length];
  29. // 然后读取指定长度的消息即可
  30. inputStream.read(bytes);
  31. System.out.println("get message from client: " + new String(bytes, "UTF-8"));
  32. }
  33. inputStream.close();
  34. socket.close();
  35. server.close();
  36. }
  37. }

先读取两个字节的长度,然后读取消息,客户端程序:

  1. import java.io.OutputStream;
  2. import java.net.Socket;
  3.  
  4. public class SocketClient {
  5. public static void main(String args[]) throws Exception {
  6. // 要连接的服务端IP地址和端口
  7. String host = "127.0.0.1";
  8. int port = 55533;
  9. // 与服务端建立连接
  10. Socket socket = new Socket(host, port);
  11. // 建立连接后获得输出流
  12. OutputStream outputStream = socket.getOutputStream();
  13. String message = "the first message!";
  14. //首先需要计算得知消息的长度
  15. byte[] sendBytes = message.getBytes("UTF-8");
  16. //然后将消息的长度优先发送出去
  17. outputStream.write(sendBytes.length >>8);
  18. outputStream.write(sendBytes.length);
  19. //然后将消息再次发送出去
  20. outputStream.write(sendBytes);
  21. outputStream.flush();
  22. //==========此处重复发送一次,实际项目中为多个命名,此处只为展示用法
  23. message = "the second message!";
  24. sendBytes = message.getBytes("UTF-8");
  25. outputStream.write(sendBytes.length >>8);
  26. outputStream.write(sendBytes.length);
  27. outputStream.write(sendBytes);
  28. outputStream.flush();
  29. //==========此处重复发送一次,实际项目中为多个命名,此处只为展示用法
  30. message = "the third message!";
  31. sendBytes = message.getBytes("UTF-8");
  32. outputStream.write(sendBytes.length >>8);
  33. outputStream.write(sendBytes.length);
  34. outputStream.write(sendBytes);
  35.  
  36. outputStream.close();
  37. socket.close();
  38. }
  39. }

运用线程池处理并发:

    服务端:

  1. import java.io.InputStream;
  2. import java.net.ServerSocket;
  3. import java.net.Socket;
  4. import java.util.concurrent.ExecutorService;
  5. import java.util.concurrent.Executors;
  6.  
  7. public class SocketServer {
  8. public static void main(String args[]) throws Exception {
  9. // 监听指定的端口
  10. int port = 55533;
  11. //建立服务端
  12. ServerSocket server = new ServerSocket(port);
  13. // server将一直等待连接的到来
  14. System.out.println("server将一直等待连接的到来");
  15.  
  16. //如果使用多线程,那就需要线程池,防止并发过高时创建过多线程耗尽资源
  17. ExecutorService threadPool = Executors.newFixedThreadPool(100);
  18.  
  19. while (true) {
  20. //建立会话
  21. Socket socket = server.accept();
  22.  
  23. // Runnable runnable=new Runnable() {
  24. // @Override
  25. // public void run() {
  26. // }
  27. // };
  28. // java8 lambda 用于简化匿名类
  29. Runnable runnable=()->{
  30. try {
  31. // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
  32. InputStream inputStream = socket.getInputStream();
  33. byte[] bytes = new byte[1024];
  34. int len;
  35. StringBuilder sb = new StringBuilder();
  36. while ((len = inputStream.read(bytes)) != -1) {
  37. // 注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
  38. sb.append(new String(bytes, 0, len, "UTF-8"));
  39. }
  40. System.out.println("get message from client: " + sb);
  41. inputStream.close();
  42. socket.close();
  43. } catch (Exception e) {
  44. e.printStackTrace();
  45. }
  46. };
  47. threadPool.submit(runnable);
  48. }
  49.  
  50. }
  51. }

TCP客户服务端的更多相关文章

  1. 利用select实现IO多路复用TCP服务端

    一.相关函数 1.  int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeva ...

  2. TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端

    目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP部分的使用 框架源码结构 补充说明 源码地址 说明 之前有好几篇博客在讲TCP/UDP通信方 ...

  3. Java网络编程(TCP服务端)

    /* * TCP服务端: * 1.创建服务端socket服务,并监听一个端口 * 2.服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象 * 3.可以通过获 ...

  4. Java TCP服务端向客户端发送图片

    /** * 1.创建TCP服务端,TCP客户端 * 2.服务端等待客户端连接,客户端连接后,服务端向客户端写入图片 * 3.客户端收到后进行文件保存 * @author Administrator * ...

  5. TCP服务端开发为例--web开发不同url请求走不同control方法

    拿java的web开发为例子,相信有很多小伙伴是做j2EE开发的,htpp请求,json数据传输都是工作中经常用的,查询请求,添加请求,修改请求前端配个url,例如https://localhost/ ...

  6. 03-案例——多任务版TCP服务端程序开发

    案例——多任务版TCP服务端程序开发   1. 需求     目前我们开发的TCP服务端程序只能服务于一个客户端,如何开发一个多任务版的TCP服务端程序能够服务于多个客户端呢?完成多任务,可以使用线程 ...

  7. Asp.Net项目与TCP服务端交互

    private void SocketSend(string sendstr) { //将字符串转换成字节数组 Byte[] fsSize = System.Text.Encoding.Default ...

  8. 【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端

    [转]TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端).UDP客户端 目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP ...

  9. python创建tcp服务端和客户端

    1.tcp服务端server from socket import * from time import ctime HOST = '' PORT = 9999 BUFSIZ = 1024 ADDR ...

随机推荐

  1. [luoguP1415] 拆分数列(DP)

    传送门 t(i,j)表示下标从i到j的数 d[i]表示以i结尾的最小的数的下标 d[i]=max(j) (1<=j<=i && t(d[j-1],j-1)<t(j,i ...

  2. BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 【广义后缀自动机】

    题目 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴 ...

  3. 刷题总结——spoj1812(后缀自动机+DP)

    题目: A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is t ...

  4. essential c++ 随笔

    编写一个C++程序: vector初始化两种方法: vector<int>elem_seq(seq_size); elem_seq[0]=1 elem_seq[1]=2; 另一种方法则是利 ...

  5. hdu4035 Maze (树上dp求期望)

    dp求期望的题. 题意: 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 从结点1出发,开始走,在每个结点i都有3种可能: 1.被杀死,回到结点1处(概率为ki) 2.找到出口,走出迷宫 ...

  6. request.getContextPath是为了解决相对路径的问题,可返回站点的根路径

    假定你的web application 名称为news,你在浏览器中输入请求路径: http://localhost:8080/news/main/list.jsp 则执行下面向行代码后打印出如下结果 ...

  7. N*N数码问题

    奇数码问题 时间限制: 1 Sec  内存限制: 128 MB 题目描述 你一定玩过八数码游戏,它实际上是在一个3*3的网格中进行的,1个空格和1~8这8个数字恰好不重不漏地分布在这3*3的网格中. ...

  8. 征途(bzoj 4518)

    Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜 ...

  9. 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证)

    一.前言 在各种Tomcat相关书籍,书上都提到了其类加载器结构: 在Tomcat 7或者8中,共享类和Catalina类加载器在catalina.properties中都是没配置的,请看: 所以,c ...

  10. android Containers控件

    1.RadioGroup 一组单选框容器 2.ListView 3.GridView 4.ExpandableListView 可折叠列表 5.ScrollView 上下滚动条 6.Horizonta ...