文章目录

  • 写在前面
  • 内容
    • API
      • C
      • Java
        • Socket
        • ServerSocket
      • Dart
    • 代码示例
      • C
        • 服务端
        • 客户端
      • Java
        • 服务端
        • 客户端
      • Dart
  • 参考

写在前面

在编程里,我们使用 Socket 来实现 TCP 或 UDP 的通信,Socket 是对它们的上层封装。虽然是不同的语言,但它们的 API 接口都遵循一致的逻辑。本篇主要是使用不同语言(C、Java 和 Dart),通过其 Socket API 来实现一个简单的 TCP 通信进行记录。

内容

API

这里主要罗列几种语言使用 Socket 时的几个基本 API,能够完成一个大致的流程。

C

在 C 语言的sys/socket.h头文件里定义了使用 Socket 的几个 API ,分别是:

  • int socket(int domain , int type , int protocol);

    • 创建套接字
  • int bind(int sockfd , struct sockaddr *myaddr , socklen_t addrlen);
    • 绑定 IP 地址和端口(服务端调用)
  • int listen(int sockfd , int backlog);
    • 进入等待连接请求状态(服务端使用)
  • int accept(int sockfd , struct sockaddr *addr , socklen_t * addrlen);
    • 受理客户端连接请求(服务端使用)
  • int connect(int sockfd , struct sockaddr *serv_addr , socklen_t addrlen);
    • 客户端请求连接(客户端调用)
  • ssize_t write(int fd , const void * buf , size_t nbytes);
    • 写数据
  • ssize_t read(int fd , void * buf , size_t nbytes);
    • 读数据
  • int close(int fd);
    • 关闭

不管是客户端还是服务端,C 语言里都是先使用 socket()进行创建。

Java

Java 里创建 Socket 的时候,客户端和服务端会使用不同的类,客户端使用的是 Socket类,服务端使用的是ServerSocket

Socket

  • Socket()

    • 创建套接字
  • public void connect(SocketAddress endpoint)
    • 连接到服务端
  • public InputStream getInputStream()
    • 获取输入流(服务端传来的)
  • public OutputStream getOutputStream()
    • 获取输出流(用于传数据给服务端)
  • public synchronized void close()
    • 关闭 Socket(同时会关闭其输入流和输出流)

ServerSocket

  • ServerSocket()

    • 创建套接字
  • public void bind(SocketAddress endpoint)
    • 绑定 IP 地址和端口
  • public Socket accept()
    • 监听连接的到来,并获取到一个新的 Socket,这个 Socket 就是客户端的操作对象
  • public void close()
    • 关闭 Socket

因为服务端通过accept()拿到了操作客户端的对象,所以输入输出也就对应Socket的 API。

Dart

待续

代码示例

C

服务端

echo_sever.c#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024
void error_handling(char *message);int main(int argc, char const *argv[])
{int serv_sock;int clnt_sock;struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;socklen_t clnt_addr_size;int str_len, i;char message[]="hello world!";if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}serv_sock = socket(PF_INET , SOCK_STREAM , 0);if(serv_sock == -1){error_handling("socket() error");}memset(&serv_addr , 0 , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(atoi(argv[1]));if(bind(serv_sock , (struct sockaddr*) &serv_addr , sizeof(serv_addr)) == -1){error_handling("bind() error");}if(listen(serv_sock , 5) == -1){error_handling("listen() error");}clnt_addr_size = sizeof(clnt_addr);for (int i = 0; i < 5; i++){clnt_sock = accept(serv_sock , (struct sockaddr*)&clnt_addr , &clnt_addr_size);if(clnt_sock == -1){error_handling("accept() error");}else{printf("Connected client %d \n" , i+1);}while((str_len = read(clnt_sock , message , BUF_SIZE)) != 0){write(clnt_sock , message , str_len);}close(clnt_sock);}close(serv_sock);return 0;
}void error_handling(char *message){fputs(message , stderr);fputc('\n' , stderr);exit(1);
}

客户端

echo_client.c#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024
void error_handling(char *message);int main(int argc, char const *argv[])
{int sock;struct sockaddr_in serv_addr;char message[30];int str_len;if(argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}sock = socket(PF_INET , SOCK_STREAM , 0);if(sock == -1){error_handling("socket() error");}memset(&serv_addr , 0 , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));if(connect(sock , (struct sockaddr*)&serv_addr , sizeof(serv_addr)) == -1){error_handling("connect() error");}else{puts("Connected............");}while(1){fputs("Input message(Q to quit): " , stdout);fgets(message , BUF_SIZE , stdin);if(!strcmp(message , "q\n") || !strcmp(message , "Q\n")){break;}write(sock , message , strlen(message));str_len = read(sock , message , BUF_SIZE-1);message[str_len] = 0;printf("Message from server : %s \n", message);}close(sock);return 0;
}void error_handling(char *message){fputs(message , stderr);fputc('\n' , stderr);exit(1);
}

Java

服务端

public class Server {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(2000);System.out.println("服务器准备就绪");System.out.println("服务端信息 : " + serverSocket.getInetAddress() + " P : " + serverSocket.getLocalPort());// 等待客户端连接for (; ; ) {// 得到客户端Socket clientSocket = serverSocket.accept();// 构建异步线程用于处理多个到来的客户端ClientHandler clientHandler = new ClientHandler(clientSocket);clientHandler.start();}}// 定义一个线程类private static class ClientHandler extends Thread {private Socket socket;private boolean flag = true;public ClientHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {super.run();System.out.println("新客户端连接 : " + socket.getInetAddress() + " P : " + socket.getPort());try {// 得到打印流,用于数据输出;服务器回送数据使用PrintStream socketOutput = new PrintStream(socket.getOutputStream());// 得到输入流,用于接收数据BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));do {// 从客户端拿到数据String str = socketInput.readLine();if ("bye".equalsIgnoreCase(str)) {flag = false;// 回送 byesocketOutput.println("bye");} else {System.out.println(str);socketOutput.println("接收到的数据长度为 : " + str.length());}} while (flag);socketInput.close();socketOutput.close();} catch (Exception e) {System.out.println("连接异常断开");} finally {// 关闭连接try {socket.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("客户端已关闭 : " + socket.getInetAddress() + " P : " + socket.getPort());}}
}

客户端

public class Client {public static void main(String[] args) throws IOException {Socket socket = new Socket();socket.setSoTimeout(3000);socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), 2000), 3000);System.out.println("已发送服务器连接");System.out.println("客户端信息 : " + socket.getLocalAddress() + " P : " + socket.getLocalPort());System.out.println("服务端信息 : " + socket.getInetAddress() + " P : " + socket.getPort());try {todo(socket);} catch (Exception e) {System.out.println("异常关闭");}socket.close();socket.shutdownInput();System.out.println("客户端已退出");}private static void todo(Socket client) throws IOException {// 构建键盘输入流InputStream systemInputStream = System.in;BufferedReader inputReader = new BufferedReader(new InputStreamReader(systemInputStream));// 得到 Socket 输入流,并转换为打印流OutputStream outputStream = client.getOutputStream();PrintStream socketPrintStream = new PrintStream(outputStream);// 获取 Socket 输入流,即服务端输入进来的InputStream inputStream = client.getInputStream();BufferedReader socketBufferedReader = new BufferedReader(new InputStreamReader(inputStream));// 轮询boolean flag = true;do {// 键盘读取一行String str = inputReader.readLine();// 发送到服务器socketPrintStream.println(str);// 从服务器读取一行String echo = socketBufferedReader.readLine();if ("bye".equalsIgnoreCase(echo)) {flag = false;} else {System.out.println(echo);}} while (flag);// 资源释放socketPrintStream.close();socketBufferedReader.close();}
}

Dart

待续

参考

《TCP/IP网络编程》

网络编程 : 几种语言使用 Socket 实现 TCP相关推荐

  1. [python学习] 专题七.网络编程之套接字Socket、TCP和UDP通信实例

    很早以前研究过C#和C++的网络通信,参考我的文章:                  C#网络编程之Tcp实现客户端和服务器聊天                 C#网络编程之套接字编程基础知识   ...

  2. Python网络编程-一文厘清socket、TCP和UDP那点事

    文章目录 网络基础 网络协议 IP地址与端口 socket套接字 概念 Python中socket模块 TCP下的服务器与客户端 TCP工作原理 TCP服务器的实现 TCP客户端的实现 UDP下的服务 ...

  3. 编程每种语言有什么用_每种情况的最佳编程语言

    编程每种语言有什么用 有一个问题,很多人都认为提问者根本不理解该主题. 有些人甚至觉得它很生气. 问题的形式通常是什么是最佳X? 什么是最好的车? 最好的编程语言是什么? 但是同时,这是一个问题,我们 ...

  4. 少儿编程几种语言_您使用了几种编程语言?

    少儿编程几种语言 机器说一种语言,但是人类却说多种不同的语言...编程语言,从Python到JavaScript等等. 一切始于Grace Hopper. "该语言中最具破坏力的短语是: 一 ...

  5. 网络编程套接字(Socket编程)

    Socket:Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元. Socket API 分类: 1.UDP数据报套接字编程: DatagramSock ...

  6. 网络编程+go+java_GO语言的进阶之路-网络编程之socket

    GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...

  7. socket网络编程常用C语言api函数(Linux)

    参考<Linux高性能服务器编程> 网络编程常用函数 字节序 ip转换 地址结构体 socket相关函数 数据读写 获取地址信息 获取或者设置套接字属性 通过域名或地址获取主机信息 字节序 ...

  8. Linux网络编程 五种I/O 模式及select、epoll方法的理解

    近期一次面试机会让我觉得有很多地方理解可能不到位,翻翻谷歌的资料加深对一些技术的理解 五种I/O 模式: [1] 阻塞 I/O (Linux下的I/O操作默认是阻塞I/O,即open和socket创建 ...

  9. Java之初步识别网络编程:IP、端口号、TCP/UDP、Socket、URL等

    文章目录 一.网络编程概述 二.网络通信要素概述 三.通信要素1:IP和端口号 IP相关 InetAdress类 如何实例化InetAddress 端口号 四.通信要素2:网络协议 TCP/IP协议簇 ...

最新文章

  1. Windows Phone开发(36):动画之DoubleAnimation 转:http://blog.csdn.net/tcjiaan/article/details/7521388...
  2. STM32时钟源时钟系统配置
  3. 【机器学习_4】机器学习算法分类
  4. python next day_PYTHON养成日记 DAY-13
  5. 复利计算再升级——连接数据库
  6. 世界上最长的博士论文,列入吉尼斯世界纪录
  7. java私有变量和_java – 大内部类和私有变量
  8. Linux源码安装pgadmin4,Linux 服务器部署 PgAdmin 4 Server
  9. 基于JAVA+SpringMVC+Mybatis+MYSQL的学生请假管理系统
  10. 【毕业答辩】别小看毕业答辩PPT,它和你的论文一样重要
  11. python设置字符编码_python字符编码问题一则
  12. 博客园添加背景音乐,给你的博文加点料
  13. Hive教程(02)- Hive安装
  14. multi task训练torch_torch中创建multitask网络结构
  15. 5线上模式刷2亿bug_GTA5还想冲销量?玩家利用BUG刷钱,遭受比封号更严厉惩罚
  16. 【极客学院】-iOS学习笔记-2-Xcode(安装,创建项目,工作空间)
  17. QQ浏览器登陆微信后,下载接收的文件保存在了哪里
  18. 细观Google全面大揭秘
  19. Git 修改 commit author
  20. 全国计算机自考应用题,近几年度自考管理系统中计算机硬应用题汇总.doc

热门文章

  1. mysql general error,mysql General error: 1267 Illegal mix of collations错误​
  2. ajax unauthorized,七牛fetch接口抓取第三方资源(网络图片),Js写ajax请求返回error错误信息总是“Unauthorized”...
  3. 1582年10月5日是个很奇怪的日子
  4. 程序员猪队友,差到大家都害怕他提交代码...
  5. Java程序员认证考试 ---SUN认证
  6. [转]对于WOW商业系统的回顾
  7. # 前端基础(HTML + CSS + JavaScript)
  8. 欢迎使用CSDN-markdown编辑器顶顶顶顶顶顶顶顶顶顶
  9. linux 获取文件名函数,Linux shell中提取文件名和路径
  10. 32位的SSDT表结构浅析