前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tcp socket api

tcp socket api

作者头像
changan
发布2020-11-04 15:04:04
5060
发布2020-11-04 15:04:04
举报

socket是网络协议栈的抽象

socket api在tcp中的体现

image
image

TCP三次握手后有个accept队列,进到这个队列才能从Listen变成accept,默认backlog 值是50。

如上图所示,这里有两个队列:syns queue(半连接队列);accept queue(全连接队列) 三次握手中,在第一步server收到client的syn后,把相关信息放到半连接队列中,同时回复syn+ack给client,第三步的时候server收到client的ack,如果这时全连接队列没满,那么从半连接队列拿出相关信息放入到全连接队列中。

当接收到3次握手中的ACK分组时,将它们移动到accept队列。 显而易见,accept系统调用只是简单地从完成队列中取出连接。 在这种情况下,listen syscall的backlog参数表示完成队列的大小。

code

代码语言:javascript
复制
/*
tcpechosvr.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>

#define SRVIP "127.0.0.1"
#define SRVPORT 10005
#define MAX_NUM 1024

int main()
{
   int serverSock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(serverSock < 0)
    {
        printf("socket creation failed\n");
        exit(-1);
    }
    printf("socket create successfully.\n");

    struct sockaddr_in serverAddr;
    memset(&serverAddr,0,sizeof(serverAddr));
    serverAddr.sin_family=AF_INET;
    serverAddr.sin_port = htons((u_short)SRVPORT);
    serverAddr.sin_addr.s_addr = inet_addr(SRVIP);

    if(bind(serverSock, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr))==-1)
    {
        printf("Bind error.IP[%s], Port[%d]\n", SRVIP, serverAddr.sin_port);
        exit(-1);
    }
    printf("Bind successful.IP[%s], Port[%d]\n", SRVIP, serverAddr.sin_port);

        /*  把sock链接进入监听哈希表listening_hash & 创建半连接队列的实例,初始化全连接队列 */
    if(listen(serverSock,10)==-1)
    {
        printf("Listen error!\n");
    }
    printf("Listening on port[%d]\n", serverAddr.sin_port);

    char recvBuf[MAX_NUM]={0};
    while(1)
    {
        struct sockaddr clientAddr;
        int size = sizeof(clientAddr);

        /* 从全连接队列中取  */
        int clientSock = accept(serverSock, &clientAddr, &size);
        printf("***SYS***    New client touched.\n");
        while(1)
        {
            //一直接收客户端socket的send操作
            if(recv(clientSock, recvBuf, MAX_NUM, 0) == -1)
            {
                printf("read error.\n");
            }
            else
            {
                printf("receiv from client:%s\n",recvBuf);
            }

            // 向客户端发送套接字
            if(send(clientSock, recvBuf , sizeof(recvBuf), MSG_NOSIGNAL) == -1)
            {
                printf("Send error!\n");
            }
            else
            {
                printf("Send to client:%s\n", recvBuf);
            }
            if( strcmp(recvBuf, "bye") == 0)
            {
                break;
            }
            memset(recvBuf, 0, sizeof(recvBuf));
        }
        close(clientSock);
    }
    close(serverSock);
    return 0;
}

REF

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • socket是网络协议栈的抽象
  • socket api在tcp中的体现
  • code
  • REF
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档