Socket编程实践(3) --Socket API

简介: socket函数#include #include int socket(int domain, int type, int protocol);创建一个套接字用于通信参数: ...

socket函数

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

创建一个套接字用于通信

参数:

   domain:指定通信协议族(protocol family),常用取值AF_INET(IPv4)

   type:指定socket类型, 流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW

   protocol:协议类型,常用取值0, 使用默认协议

返回值:

   成功: 返回非负整数,套接字;

   失败: 返回-1


bind函数

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

绑定一个本地地址到套接字

参数:

   sockfd:socket函数返回的套接字

   addr:要绑定的地址

//sockaddr_in结构, bind时需要强制转换成为struct sockaddr*类型
struct sockaddr_in
{
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};
/* Internet address. */
struct in_addr
{
    uint32_t       s_addr;     /* address in network byte order */
};
/**示例:INADDR_ANY的使用, 绑定本机任意地址**/
int main()
{
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1)
        err_exit("socket error");

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8001);
    //绑定本机的任意一个IP地址, 作用同下面两行语句
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    //inet_aton("127.0.0.1", &addr.sin_addr);
    //addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    if (bind(listenfd, (const struct sockaddr *)&addr, sizeof(addr)) == -1)
        err_exit("bind error");
    else
        cout << "bind success" << endl;
}

listen函数

int listen(int sockfd, int backlog);

   listen函数应该用在调用socketbind函数之后, 并且用在调用accept之前用于将一个套接字从一个主动套接字转变成为被动套接字。

backlog说明:

对于给定的监听套接口,内核要维护两个队列:

   1、已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程(SYN_RCVD状态)

   2、已完成连接的队列(ESTABLISHED状态)

但是两个队列长度之和不能超过backlog


backlog推荐使用SOMAXCONN(3.13.0-44-generic中该值为128), 使用等待队列的最大值;

 

Man-Page中的listen说明:

   listen() marks the socket referred to by sockfd as a passive socket, that is, as a socket that 

will be used to accept incoming connection requests using accept(2).

   The sockfd argument is a file descriptor that refers to a socket of type  SOCK_STREAM  or 

SOCK_SEQPACKET.

   The backlog argument defines the maximum length to which the queue of pending connections for 

sockfd may grow.  If a connection request arrives when the queue is full, the  client may  receive

an  error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, 

the request may be ignored so that a later reattempt at  connection succeeds.

  If the backlog argument is greater than the value in  /proc/sys/net/core/somaxconn(Ubuntu 14.04 该值为128),  then it  is  silently truncated to that value; the default value in this file is 128.  In kernels

before 2.4.25, this limit was a hard coded value, SOMAXCONN, with the value 128.

 

accept函数

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

已完成连接队列返回第一个连接(the first connection request on the queue of  pending  connections  for the listening 

socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. 

The newly created socket  is  not  in  the listening state),如果已完成连接队列为空,则阻塞。The original 

socket sockfd is unaffected by this call.

 

参数:

   sockfd:服务器套接字

   addr:将返回对等方的套接字地址, 不关心的话, 可以设置为NULL

   addrlen:返回对等方的套接字地址长度, 不关心的话可以设置成为NULL, 否则一定要初始化

返回值:

   On  success, these system calls return a non-negative integer that is a descriptor for the accepted 

socket.  On error, -1 is returned, and errno is set appropriately.

 

connect函数

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

建立一个连接至addr所指定的套接字

参数:

   sockfd:未连接套接字

   addr:要连接的套接字地址

   addrlen:第二个参数addr长度

 

示例:echo server/client实现

//server端代码
int main()
{
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1)
        err_exit("socket error");

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8001);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(listenfd, (const struct sockaddr *)&addr, sizeof(addr)) == -1)
        err_exit("bind error");
    if (listen(listenfd, SOMAXCONN) == -1)
        err_exit("listen error");

    char buf[512];
    int readBytes;
    struct sockaddr_in clientAddr;
    //谨记: 此处一定要初始化
socklen_t addrLen = sizeof(clientAddr);
    while (true)
    {
        int clientfd = accept(listenfd, (struct sockaddr *)&clientAddr, &addrLen);
        if (clientfd == -1)
            err_exit("accept error");
        //打印客户IP地址与端口号
        cout << "Client information: " << inet_ntoa(clientAddr.sin_addr)
             << ", " << ntohs(clientAddr.sin_port) << endl;

        memset(buf, 0, sizeof(buf));
        while ((readBytes = read(clientfd, buf, sizeof(buf))) > 0)
        {
            cout << buf;
            if (write(clientfd, buf, readBytes) == -1)
                err_exit("write socket error");
            memset(buf, 0, sizeof(buf));
        }
        if (readBytes == 0)
        {
            cerr << "client connect closed..." << endl;
            close(clientfd);
        }
        else if (readBytes == -1)
            err_exit("read socket error");
    }
    close(listenfd);
}
//client端代码
int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
        err_exit("socket error");

    //填写服务器端口号与IP地址
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8001);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    if (connect(sockfd, (const struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
        err_exit("connect error");

    char buf[512];
    while (fgets(buf, sizeof(buf), stdin) != NULL)
    {
        if (write(sockfd, buf, strlen(buf)) == -1)
            err_exit("write socket error");
        memset(buf, 0, sizeof(buf));
        int readBytes = read(sockfd, buf, sizeof(buf));
        if (readBytes == 0)
        {
            cerr << "server connect closed... \nexiting..." << endl;
            break;
        }
        else if (readBytes == -1)
            err_exit("read socket error");
        cout << buf;
        memset(buf, 0, sizeof(buf));
    }
    close(sockfd);
}

附-Makefile

.PHONY: clean all 
CC = g++ 
CPPFLAGS = -Wall -g -pthread -std=c++11
BIN = server client
SOURCES = $(BIN.=.cpp)

all: $(BIN)
$(BIN): $(SOURCES) 

clean:
    -rm -rf $(BIN) bin/ obj/ core


目录
相关文章
|
3月前
|
监控 供应链 搜索推荐
电商数据开发实践:深度剖析1688商品详情 API 的技术与应用
在电商数字化转型中,数据获取效率与准确性至关重要。本文介绍了一款高效商品详情API,具备全维度数据采集、价格库存管理、多媒体资源获取等功能,结合实际案例探讨其在电商开发中的应用价值与优势。
|
3月前
|
前端开发 Java API
利用 Spring WebFlux 技术打造高效非阻塞 API 的完整开发方案与实践技巧
本文介绍了如何使用Spring WebFlux构建高效、可扩展的非阻塞API,涵盖响应式编程核心概念、技术方案设计及具体实现示例,适用于高并发场景下的API开发。
360 0
|
4月前
|
JSON API UED
运营商二要素验证 API:核验身份的一致性技术实践(Python示例)
随着线上业务快速发展,远程身份核验需求激增。运营商二要素验证API通过对接三大运营商实名数据,实现姓名、手机号、身份证号的一致性校验,具备权威性高、实时性强的优势,广泛应用于金融、电商、政务等领域。该接口支持高并发、低延迟调用,结合Python示例可快速集成,有效提升身份认证的安全性与效率。
529 0
|
5月前
|
缓存 监控 搜索推荐
电商生态协同的关键:API接口在电商数据对接中的应用与实践
电商数据对接API接口是连接电商平台与外部系统的智慧桥梁,通过标准化协议实现商品管理、订单处理、支付结算、物流追踪及数据分析等全链路支持。本文从核心功能、对接流程、应用场景和优化策略四个方面解析其技术逻辑与实践路径。API接口助力店铺管理自动化、精准营销与跨境电商全链路管理,同时通过安全防护、性能调优与合规管理提升效能,推动电商行业向智能化、高效化发展。
|
4月前
|
自然语言处理 供应链 前端开发
深度解析与技术实践:高效调用淘宝商品评论API的策略与代码实现
本文深入解析淘宝开放平台商品评论接口(Taobao.item_review),涵盖接口功能、调用逻辑与实战代码,助力开发者高效获取用户评价数据,提升电商数据分析能力。
|
6月前
|
机器学习/深度学习 JSON 算法
京东拍立淘图片搜索 API 接入实践:从图像识别到商品匹配的技术实现
京东拍立淘图片搜索 API 是基于先进图像识别技术的购物搜索接口,支持通过上传图片、URL 或拍摄实物搜索相似商品。它利用机器学习和大数据分析,精准匹配商品特征,提供高效、便捷的搜索体验。接口覆盖京东海量商品资源,不仅支持外观、颜色等多维度比对,还结合用户行为数据实现智能推荐。请求参数包括图片 URL 或 Base64 编码,返回 JSON 格式的商品信息,如 ID、价格、链接等,助力消费者快速找到心仪商品,满足个性化需求。
473 18
|
5月前
|
人工智能 自然语言处理 API
电商API技术文档编写规范白皮书:方法论与行业实践
本文系统阐述电商API接口文档的编写规范与最佳实践,涵盖结构设计、技术语言、开发者体验、版本控制及质量保障等方面,助力企业提升开发效率,构建开放共赢的电商生态。
|
2月前
|
供应链 安全 API
唯品会:利用银行转账API实现企业采购对公支付的技术实践
企业采购支付面临合规、效率与对账难题。唯品会通过银行API实现银企直连,构建安全高效对公支付系统,支持ISO 20022标准与多重风控,支付耗时从72小时降至90秒,错误率下降98%,推动供应链数字化升级。(236字)
326 1
|
2月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。
|
2月前
|
算法 API 数据库
生鲜电商技术实践:基于保质期API的自动下架系统保障食品安全
基于保质期提醒API与自动化工作流,实现生鲜商品临期智能预警与自动下架。通过设定差异化预警阈值(如蔬菜2天、冷冻品7天),每日扫描数据库并触发下架指令,确保食品安全合规,降低损耗与客诉,提升运营效率。
247 0
下一篇
oss云网关配置