socket 编程基础

TCP 服务器的工作流程:

  1. 服务器调用 socket() 创建 socket;
  2. 服务器调用 bind() 绑定端口和 ip;
  3. 服务器调用 listen() 设置缓冲区;
  4. 服务器调用 accept() 接收客户端的连接请求建立连接, 生成一个新的 socket;
  5. 服务器与客户端建立好连接之后, 就可以通过 send()/recv() 向客户端发送或者接收客户端的数据;
  6. 服务器调用 close() 关闭 socket.

客户端工作流程:

  1. 客户端调用 socket() 创建 socket;
  2. 客户端调用 connect() 向服务器发去连接请求以建立连接;
  3. 客户端与服务器建立连接之后, 就可以通过 send()/recv() 向服务器发送或者接收服务器的数据;
  4. 客户端调用 clos() 关闭 socket.
 /**
 *  创建并初始化 socket, 返回该 socket 的文件描述符, 若描述符为 -1 表示创建失败.
 参数:
 addressFamily: 是 IPv4(AF_INET)或者 IPv6(AF_INET6).
 type:          表示 socket 的类型, 通常是流(SOCK_STREAM)或者数据报文(SOCK_DGRAM).
 protocol:      通常为0, 以便让系统自动选择合适的协议,对于 SOCK_STREAM 来说会是 TCP 协议,对于 SOCK_DGRAM 来说会是 UDP 协议
 */
int socket(int addressFamily, int type, int Protocol);

        
/**
 *  关闭 socket
 */
int close(int socketFileDescriptor);
   
        
/**
 *  将 socket 与特定主机地址和端口号绑定,绑定成功返回0, 失败返回 -1;
 绑定成功后可进行不同的操作:
 UDP: 因为 UDP 是无连接的, 绑定之后就可以利用 UDP socket 来传数据了.
 TCP: TCP 是需要建立端到端连接的, 为了建立 TCP 连接, 服务器必须调用 listen(int socketFileDescriptor, int backlogSize)来设置服务器的缓冲区队列以接收客户端的连接请求, backlogSize 表示客户端连接请求缓冲区队列的大小. 当调用 listen 设置之后, 服务端等待客户端请求, 然后调用 listen 设置 accept 来接收客户端的连接请求.
 *
 *  @param socketFileDescriptor  socket 描述文件
 *  @param addressToBind        主机地址
 *  @param addressStructLength  主机地址结构体的长度
 */
int bind((int)socketFileDescriptor, (const struct sockaddr *)&addressToBind, (socklen_t)addressStructLength);
        

/**
 *  接受客户端连接请求并将客户端的网络地址信息保存到 childAddress 中.
 当客户端请求被服务器接受之后, 客户端和服务器之间的连接就建立了, 两者之间就可以通信了.
 注意 accept 会阻塞当前线程, 知道有客户端请求连接进来之后才会继续往下执行.
 *
 *  @param socketFileDescriptor socket 描述字
 *  @param restrict             客户端结构体地址
 *  @param restrict             客户端结构体长度地址
 *
 */
int newSocker = accept((int)socketFileDescriptor, (struct sockaddr *)&childAddress, (socklen_t *restrict)childAddressLength);
   
        
/**
 *  客户端向特定网络地址服务器发送连接请求, 连接成功后返回0, 失败返回 -1;
 当服务器建立好后, 客户端通过调用该接口向服务器发起建立连接请求. 对于 UDP 来说, 该接口是可选的, 如果调用了该接口, 表明设置了该 UDP socket 默认的网络地址. 对 TCP 来说, 这就是传说中三次握手发生的地方.
 
 注意这个接口会阻塞当前线程, 直到服务器返回信息.
 
 *  @param socketFileDescriptor socket 描述字
 *  @param serverAddress        服务器的网络地址
 *
 */
int ss = connect(int socketFileDescriptor, (const struct sockaddr *)&serverAddress, (socklen_t)serverAddressLength);
        
        
/**
 *  使用 DNS 查找特定主机名地址对应的 IP 地址, 如果找不到对应的 IP 地址 则返回 NULL.
 */
int gethostname((char *)&hostName, sizeof(host_name_t));

        
/**
 *  通过 socket 发送数据, 发送成功返回发送的字节数, 否则返回 -1;
 一旦连接建立好之后, 就可以通过 send/recv 接口发送或者接受数据了. 注意, 调用 connect 设置了默认网络地址的 UDPsocket 也可以调用该接口来发送数据.
 *
 *  @param socketFileDescriptor  socket 描述字
 *  @param void                 数据容器
 */
ssize_t send((int)newSocker, (const void *)buffer, (size_t)bufferLength, int flag);


/**
 *  从 socket 中读取数据, 读取成功之后返回读取的字节数, 否则返回 -1.
 一旦连接建立好之后, 就可以接收数据了, 注意, 嗲用 connect 设置了默认网络地址的 UDPsocket 也可以调用该接口来接收数据.
 */
ssize_t recv((int)newSocker, buffer, (size_t)sizeof(buffer), int flag);


/**
 *  通过 UDPsocket 发送数据到特定的网络地址, 发送成功返回发送的字节数, 否则返回 -1.网络地址发送数据, 所以可以指定特定网络地址, 以向其发送数据.
 由于 UDP 可以向多个
 *
 *  @param socketFileDescriptor     socket 描述字
 *  @param buffer                   存放要发送的数据的容器
 *  @param destinationAddress       目标地址的 IP 地址结构体
 *  @param destinationAddressLength 目标地址结构体的长度
 */
size_t sendto((int)socketFileDescriptor, (const void *)buffer, (size_t)sizeof(buffer), int flag, (const struct sockaddr *)&destinationAddress, (socklen_t)destinationAddressLength);


/**
 *  从 UDPsocket 中读取数据, 并保存发送者的网络地址信息,读取成功返回读取的数据字节数, 否则返回 -1. 
 由于 UDP 可以接收来自多个网络地址的数据, 所以需要提供额外的参数, 以保存该数据发送者的身份.
 */
size_t recvfrom((int)socketFileDescriptor, (const void *)buffer, (size_t)sizeof(buffer), int flag, (struct sockaddr *restrict)&fromAddress, (socklen_t *restrict)&fromAddressLength); 


/**
 *  getsocketname() 可以获得一个与 socket 相关的地址.
 服务器端可以通过它得到相关客户端的地址;
 服务端也可以得到当前已连接成功的 socket 的 ip 和端口.
 
 第二种情况在客户端不进行 bind() 而直接连接服务器时, 而客户端需要知道当前使用哪个 ip 进行通信时比较有用(如多网卡的情况).
 
 对于 TCP 连接情况: 如果不使用 bind() 指定 ip 和端口, 那么调用 connect() 连接成功之后, 使用 getsocketname() 可以正确获得当前正在通信的 socket 的 ip 和端口地址.
 对于 UDP 连接情况: 无论是在调用 sendto() 之后还是在收到服务器返回的信息之后调用, 都无法得到正确的 ip 地址, 使用 getsocketname() 得到的 ip 为0, 端口正确.
 *
 *  @param int socket 描述字
 */
int getsockname((int)socketFileDescriptor, (struct sockaddr *restrict)&address, (socklen_t *restrict)&addressLength);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 1、TCP状态linux查看tcp的状态命令:1)、netstat -nat 查看TCP各个状态的数量2)、lso...
    北辰青阅读 9,423评论 0 11
  • 一 . 网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行...
    H_Man阅读 332评论 0 2
  • 最近在学习Python看了一篇文章写得不错,是在脚本之家里的,原文如下,很有帮助: 一、网络知识的一些介绍 soc...
    qtruip阅读 2,700评论 0 6
  • [TOC]
    百炼阅读 255评论 0 0
  • 永澄老师竟然免费教大家“制定半年目标”。去年跟永澄老师学习“年目标达成”课程,花了我好多钱,好心疼。学习目标管理有...
    384b82bbc76b阅读 217评论 0 0