【Socket】WSL下Socket编程示例及理解

本文详细介绍了在Windows Subsystem for Linux (WSL)环境下进行Socket编程的实例,包括服务端向客户端发送数据、客户端响应以及迭代回声的实现。内容涵盖了Socket通信的基础概念,如IP地址、端口、协议,以及Linux中Socket作为文件的抽象概念。通过示例代码,读者可以了解如何在C++中进行Socket编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

平台:WSL
代码功能:server 向 client 发送消息,client 读取消息并显示。
示例代码一:server 只接受一次 client 请求,当 server 向 client 传回数据后,程序就运行结束了。如果想再次接收到服务器的数据,必须再次运行 server,所以这是一个非常简陋的 socket 程序,不能够一直接受客户端的请求。
示例代码二:client 向server 发送消息,server 返回接收到的消息(回声)。
示例代码三:在示例代码二的基础上实现迭代回声。

Linux Socket 编程理解

socket 是计算机之间通信的方式。其典型应用就是 Web 服务器和浏览器:浏览器获取用户输入的URL,向服务器发起请求,服务器分析接收到的URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,就将文字、图片、视频等元素呈现给用户。

计算机通信需要知道通信对象的 ip地址(标记计算机位置,如 127.0.0.1 为本机地址) 、 端口(标记哪一个应用程序接收数据)、协议(通信双方必须使用同一种协议才能通信)、数据传输方式(面向连接 SOCK_STREAM 无连接 SOCK_DGRAM)。

0

Linux下一切皆文件,除了文本文件、源文件、二进制文件等,一个硬件设备也可以被映射为一个虚拟的文件,称为设备文件。对于所有的文件,都可以使用 read() 函数读取数据,使用 write() 函数写入数据。

所有在Linux中创建的文件都有一个 int 类型的编号,称为文件描述符(File Descriptor),Windows下称为文件句柄(File Handle)。使用文件时,只要知道文件描述符就可以。例如,stdin 的描述符为 0,stdout 的描述符为 1。

在Linux中,socket 可以看作一种文件,可以认为,两台计算机之间的通信,实际上是两个 socket 文件的相互读写。

//I. socket()创建套接字
//在 Linux 下使用 <sys/socket.h> 头文件中 socket() 函数来创建套接字
//1) af 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF 是“Address Family”的简写,INET是“Inetnet”的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1(本机地址);AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。
//2) type 为数据传输方式,常用的有 SOCK_STREAM 和 SOCK_DGRAM。
//3) protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。
int socket(int af, int type, int protocol);
int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  //IPPROTO_TCP表示TCP协议
int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  //IPPROTO_UDP表示UDP协议
//系统自动推演(协议参数置0)写法:
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);  //创建TCP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);  //创建UDP套接字


//II. bind()绑定套接字
//sock 为 socket 文件描述符,addr 为 sockaddr 结构体变量的指针,addrlen 为 addr 变量的大小,可由 sizeof() 计算得出。
int bind(int sock, struct sockaddr *addr, socklen_t addrlen);


//III. connect()建立连接
int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen);

//IV. listen()进入监听状态
int listen(int sock, int backlog); //sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度,缓冲区的长度(能存放多少个客户端请求)


//V. accept()接收客户端请求
//accept() 返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字,大家注意区分。后面和客户端通信时,要使用这个新生成的套接字,而不是原来服务器端的套接字。
int accept(int sock, struct sockaddr *addr, socklen_t *addrlen);

//VI. write() / read() 数据收发
//fd 为要写入的文件的描述符,buf 为要写入的数据的缓冲区地址,nbytes 为要写入的数据的字节数。
//size_t 是通过 typedef 声明的 unsigned int 类型;ssize_t 在 "size_t" 前面加了一个"s",代表 signed,即 ssize_t 是通过 typedef 声明的 signed int 类型。
//write() 函数会将缓冲区 buf 中的 nbytes 个字节写入文件 fd,成功则返回写入的字节数,失败则返回 -1。read() 函数会从 fd 文件中读取 nbytes 个字节并保存到缓冲区 buf,成功则返回读取到的字节数(但遇到文件结尾则返回0),失败则返回 -1。
ssize_t write(int fd, const void *buf, size_t nbytes);
ssize_t read(int fd, void *buf, size_t nbytes);

示例代码一 服务端向客户端发送数据

server.cpp

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(){
   
    //创建套接字
    //AF_INET 表示使用 IPv4 地址,SOCK_STREAM 表示使用面向连接的数据传输方式,IPPROTO_TCP 表示使用 TCP 协议
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //将套接字和IP、端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值