Posted on:
Last modified:
创建与使用 socket, 一个 echo server 和 client
socket 客户端的四个步骤:
第一步 创建一个 TCP socket int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 返回的 sock 可以看做一个 handle, 本质上是一个文件描述符 ( file descriptor) , 小于 0 表示错误
表示 socket 地址的结构 sockaddr_in, 其中 in 表示 internet, 不是 input
struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
其中 sin_family 和 sin_port 和 sin_addr.s_addr 字段必须填写
使用 inet_pton 把 IP 字符串转化为 32 位整形 端口号需要使用 htons 转化
下一步就是连接了,注意 connect 和好多函数都要求把参数从 sockaddr_in 转化到 sockaddr, 然后再跟一个参数表示实际的数据结构的长度。这是因为 C 不支持多态。
第三步就是发送和接收数据,我们使用 send 函数发送,send 成功的话会返回发送成功的数据的长度,可能和指定的数据不等,因此需要判断是否发送成功。recv 也可能返回任意长度的数据,因此需要在一个循环里接受。send 和 recv 都是阻塞的
int send(int socket, const void* buffer, size_t length, int flags);
int recv(int socket, const void* buffer, size_t length, int flags);
最后关闭连接
需要特别注意的是,永远不要把来自其他主机的消息使用 pritnf 等不安全的函数打印出来
socket 服务器的四个流程
第一步,创建 socket, 和客户端完全一样 注意,服务端的地址有所不同,为了接受任何一个客户,我们需要监听服务器的所有 IP (服务器可能有多个网卡,也就有多个 IP).
第二步,使用 bind 绑定到对应的 ip 和端口号,listen 把 socket 设定为监听状态。注意 listen 还有一个参数代表
第三步,使用 accept 开始阻塞地等待客户端。注意 accept 实际上有两个返回值,一个通过函数返回的形式返回一个客户端的 socket, 还有一个通过指针的形式返回一个 sockaddr_in
第四步,接下来,把每一个获得的 client socket 都对应地处理
关闭主 socket
最后需要注意的是,
inet_pton/inetntop htons, ntohs, htonl, ntohl
相比来说,UDP 就非常简单了,相对于 TCP 在 IP 层之上提供个各种服务,UDP 只添加了两项,端口号和校验,而且只是简单地把校验出错的包丢掉。
© 2016-2022 Yifei Kong. Powered by ynotes
All contents are under the CC-BY-NC-SA license, if not otherwise specified.
Opinions expressed here are solely my own and do not express the views or opinions of my employer.
友情链接: MySQL 教程站