Slide 1

Similar documents
Slide 1

引言 ftp 工作原理 FTP 客户端思考练习 要点回顾 1 ip 地址结构 2 字节顺序转换函数 3 IP 格式转换函数 2 / 29

CC213

C6_ppt.PDF

C 1

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco

新・明解C言語入門編『索引』


(Methods) Client Server Microsoft Winsock Control VB 1 VB Microsoft Winsock Control 6.0 Microsoft Winsock Control 6.0 1(a). 2

新・解きながら学ぶC言語

C/C++ - 文件IO

新版 明解C言語入門編

新版 明解C++入門編

untitled






untitled

untitled

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

C/C++ - 字符输入输出和字符确认

untitled

chap07.key


【主持人】:给大家介绍一下,这次的培训是我们画刊部的第三次培训,当然今天特别有幸请来著吊的摄影家李少白老师给我们讲课

Microsoft Word - Broker.doc

FY.DOC

ACE

untitled

static struct file_operations gpio_ctl_fops={ ioctl: gpio_ctl_ioctl, open : gpio_open, release: gpio_release, ; #defineled1_on() (GPBDAT &= ~0x1) #def

Java

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

关于建立境内违法互联网站黑名单管理制度的通知

? 這 全 都 是 市 政 府 提 供 給 我 的 資 料 低 底 盤 公 車 計 畫 96 年 預 算 新 台 幣 4,500 萬 元 97 年 預 算 新 台 幣 1 億 6,500 萬 元 98 年 預 算 新 台 幣 3 億 2,300 萬 元, 共 有 307 台 低 底 盤 公 車,99

Microsoft Word - 实用案例.doc

epub 33-8

Chapter #

第7章-并行计算.ppt

eta6210使用手册

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

_汪_文前新ok[3.1].doc

/3/15 1, linux. linux,,. : 1.NAT ; 2. (load balance, virtual server);; 3. ; 4. ; 5. 6.VPN; 7. ; 8. ; 9.. (,

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

新・解きながら学ぶJava

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

untitled

第3章.doc

第一章 概论

C/C++ - 函数

ebook15-10

C

《C语言程序设计》教材习题参考答案

Microsoft PowerPoint - Socket programming.ppt [相容模式]

Linux網路傳輸設定

网络程序设计(socketAPI)

nooog

ebook 132-2

ebook

Socket Socket TcpClient Socket.Connect TcpClient.Connect Socket.Send / Receive NetworkStream 6-5

提问袁小兵:

《C语言程序设计》第2版教材习题参考答案

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

The golden pins of the PCI card can be oxidized after months or years

[改訂新版]C言語による標準アルゴリズム事典

W. Richard Stevens UNIX Sockets API echo Sockets TCP OOB IO C struct C/C++ UNIX fork() select(2)/poll(2)/epoll(4) IO IO CPU 100% libevent UNIX CPU IO

Microsoft Word - 第3章.doc

VoIP Make a Rtp Call VoIP Abstract... 2 VoIP RTP...3 Socket IP...9 Config Two Voice-hub

プログラムの設計と実現II

概述

Data Server_new_.doc

}; "P2VTKNvTAnYNwBrqXbgxRSFQs6FTEhNJ", " " string imagedata; if(0!= read_image("a.jpg",imagedata)) { return -1; } string rsp; ytopen_sdk m_sd

Microsoft Word - 正文.doc

C/C++程序设计 - 字符串与格式化输入/输出

Transcription:

网络编程入门篇 利用 socket 实现 TCP 服务器

目录 基础知识 具体示例 示例代码讲解

基础知识

基础知识 socket 编程一般采用客户端 - 服务器模式 ( 即由客户进程向服务器进程发出请求, 服务器进程执行请求的任务并将执行结果返回给客户进程的模式 ) 今天我们要讲的就是如何利用 socket 编程实现基于 TCP 协议通信的服务器 首先我们先向大家展示 socket 编程的流程, 然后给出具体的示例, 最后讲解一下示例代码

基础知识 TCP 服务器的 socket 编程流程, 如右图所示 : 创建 socket 将创建的 socket 绑定到一个 IP 地址和端口号上 设置 socket 为监听模式 接收请求并返回 socket 与客户端进行通信 关闭 socket

具体示例

工程配置 RT-Thread samples 软件包中已有一份该示例代码 tcpserver.c, 可以通过 env 配置将示例代码加入到项目中 按照下面的路径获取 tcp server 的示例代码 : RT-Thread online packages ---> miscellaneous packages ---> samples: RT-Thread kernel and components samples ---> network sample options ---> [*] [network] tcp server 保存并更新软件包 pkgs --update 编译工程 scons 然后运行 qemu

查看 ip 地址 在 qemu 运行起来之后, 输入命令 ifconfig 查看系统的 IP 地址

运行示例代码 在 msh 命令行下输入命令 tcpserv 即可让示例代码运行 msh /> tcpserv TCPServer Waiting for client on port 5000... 示例代码会在 qemu 上启动一个 TCP 服务器, 端口号是 5000

开启 TCP 客户端 这样我们可以在电脑上搭建一个 TCP 客户端来连接已经处于运行状态的 TCP 服务器 这里以网络调试助手 IPOP 为例 1. 如果是 QEMU 平台的话要先绑定网卡和 IP 地址 选择和开发板处于同一网段的网卡 ( 这里就是 TAP 网卡了 ) 绑定一个和开发板处于同一网段的 ip 地址 例如开发板 ip 为 192.168.137.117, 绑定的 IP 地址可以是 192.168.137.35 已经绑定过的话就不需要绑定了

开启 TCP 客户端 这样我们可以在电脑上搭建一个 TCP 客户端来连接已经处于运行状态的 TCP 服务器 这里以网络调试助手 IPOP 为例 1. 如果是 QEMU 平台的话要先绑定网卡和 IP 地址 选择和开发板处于同一网段的网卡 ( 这里就是 TAP 网卡了 ) 绑定一个和开发板处于同一网段的 ip 地址 例如开发板 ip 为 192.168.137.117, 绑定的 IP 地址可以是 192.168.137.35 已经绑定过的话就不需要绑定了

开启 TCP 客户端 然后是开启 TCP 客户端连接服务器

从客户端发消息给服务器 发送字符 'q' 断开连接, 发送 exit 关闭服务器

注意事项 电脑需要关闭防火墙

示例代码讲解

示例代码讲解 /* * 程序清单 :tcp 服务端 * * 这是一个 tcp 服务端的例程 * 导出 tcpserv 命令到控制终端 * 命令调用格式 :tcpserv * 无参数 * 程序功能 : 作为一个服务端, 接收并显示客户端发来的数据, 接收到 exit 退出程序 */ #include <rtthread.h> #include <sys/socket.h> /* 使用 BSD socket, 需要包含 socket.h 头文件 */ #include <netdb.h> #include <string.h> #define BUFSZ (1024) static const char send_data[] = "This is TCP Server from RT-Thread."; /* 发送用到的数据 */ static void tcpserv(int argc, char **argv) char *recv_data; /* 用于接收的指针, 后面会做一次动态分配以请求可用内存 */ socklen_t sin_size; int sock, connected, bytes_received; struct sockaddr_in server_addr, client_addr; rt_bool_t stop = RT_FALSE; /* 停止标志 */ int ret;

示例代码讲解 recv_data = rt_malloc(bufsz + 1); /* 分配接收用的数据缓冲 */ if (recv_data == RT_NULL) rt_kprintf("no memory\n"); return; /* 一个 socket 在使用前, 需要预先创建出来, 指定 SOCK_STREAM 为 TCP 的 socket */ if ((sock = socket(af_inet, SOCK_STREAM, 0)) == -1) /* 创建失败的错误处理 */ rt_kprintf("socket error\n"); /* 释放已分配的接收缓冲 */ rt_free(recv_data); return; /* 初始化服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(5000); /* 服务端工作的端口 */ server_addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));

示例代码讲解 /* 绑定 socket 到服务端地址 */ if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) /* 绑定失败 */ rt_kprintf("unable to bind\n"); /* 释放已分配的接收缓冲 */ rt_free(recv_data); return; /* 在 socket 上进行监听 */ if (listen(sock, 5) == -1) rt_kprintf("listen error\n"); /* release recv buffer */ rt_free(recv_data); return; rt_kprintf("\ntcpserver Waiting for client on port 5000...\n"); while (stop!= RT_TRUE) sin_size = sizeof(struct sockaddr_in);

示例代码讲解 /* 接受一个客户端连接 socket 的请求, 这个函数调用是阻塞式的 */ connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size); /* 返回的是连接成功的 socket */ if (connected < 0) rt_kprintf("accept connection failed! errno = %d\n", errno); continue; /* 接受返回的 client_addr 指向了客户端的地址信息 */ rt_kprintf("i got a connection from (%s, %d)\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); /* 客户端连接的处理 */ while (1) /* 发送数据到 connected socket */ ret = send(connected, send_data, strlen(send_data), 0); if (ret < 0) /* 发送失败, 关闭这个连接 */ closesocket(connected); rt_kprintf("\nsend error,close the socket.\r\n"); break;

示例代码讲解 else if (ret == 0) /* 打印 send 函数返回值为 0 的警告信息 */ rt_kprintf("\n Send warning,send function return 0.\r\n"); /* 从 connected socket 中接收数据, 接收 buffer 是 1024 大小, 但并不一定能够收到 1024 大小的数据 */ bytes_received = recv(connected, recv_data, BUFSZ, 0); if (bytes_received < 0) /* 接收失败, 关闭这个 connected socket */ closesocket(connected); break; else if (bytes_received == 0) /* 打印 recv 函数返回值为 0 的警告信息 */ rt_kprintf("\nreceived warning,recv function return 0.\r\n"); closesocket(connected); break; /* 有接收到数据, 把末端清零 */ recv_data[bytes_received] = '\0'; if (strcmp(recv_data, "q") == 0 strcmp(recv_data, "Q") == 0)

示例代码讲解 /* 如果是首字母是 q 或 Q, 关闭这个连接 */ closesocket(connected); break; else if (strcmp(recv_data, "exit") == 0) /* 如果接收的是 exit, 则关闭整个服务端 */ closesocket(connected); stop = RT_TRUE; break; else /* 在控制终端显示收到的数据 */ rt_kprintf("received DATA = %s \n", recv_data); /* 退出服务 */ closesocket(sock); /* 释放接收缓冲 */ rt_free(recv_data); return ; MSH_CMD_EXPORT(tcpserv, a tcp server sample);