socket网络编程之一(TCP套接字API)

socket是对TCP/IP协议族的封装,并对网络编程开发人员提供可用的接口,可以说,任何网络编程都离不开socket,要想熟练运用网络编程技术,必须掌握socketAPI.本篇文章便是对socketAPI的介绍.

套接字地址结构

IPV4套接字地址结构

typedef __uint32_t  in_addr_t;

struct in_addr {
    in_addr_t s_addr;     /* 32位的IP地址 */
};                                      /* 网络子节序 */

struct sockaddr_in {
    __uint8_t   sin_len;      /* 结构体的长度 */
    sa_family_t sin_family;      /* AF_INET协议族 */
    in_port_t   sin_port;               /* 16位的端口号,网络子节序 */
    struct  in_addr sin_addr; /* 32位IP地址 */
    char        sin_zero[8];  /* unused */
};
  • 长度字段sin_len表示struct sockaddr_in的长度,在使用的时候,并不是必须显示的对该字段赋值,它是一个无符号8位整形,即unsigned char类型
  • sin_family是一个_uint8_t类型,表示套接字地址结构的协议族,比如AF_INET表示internet协议族。
  • sin_port 是一个_unint16_t十六位无符号整形,表示TCP协议中的端口号, 是网络子节序。
  • sin_addr 是一个32位无符号整形的IP地址,将它设置成结构体类型,是为了考虑内存对齐.
  • sin_zero字段,也不需要显示设置,基本不用.

通用套接字地址结构

strict sockaddr{
     __uint8_t ss_len;
    sa_family_t  sa_family;
    char sa_data[14];
}

当套接字地址结构作为一个参数传递进任何套接字函数时,套接字地址结构总是以指针的形式来传递,然而以这样的指针作为参数之一的任何套接字函数,必须处理来自任何协议族的套接字地址结构。因此ANSIC便创造了通用套接字地址结构,当时候IPV4套接字地址结构传递时,需要进行强制转换.

套接字函数

socket函数

#inclucde<sys/socket.h>
int socket(int family,int type,int protocol);
  • socket函数在成功时,返回一个非负整数,称之为套接字描述符,失败时返回一个负数,错误信息在error中.
  • family表示协议族,比如AF_INET表示IPV4协议,AF_INET6表示IPV6协议,AF_LOCAL表示Unix表示域协议等.
  • type表示套接字类型,SOCK_STREAM表示TCP套接字,SOCK_DGRAM表示数据报套接字(UDP).protocol一般设置为0表示family和type组合的系统默认值.

connection函数

#include<sys/socket.h>
int connection(int sockfd,const struct *sockaddr,socklen_t addrlen);
  • sockfd是一个套接字描述符,由socket函数指定,第二个和第三个参数分别指定套接字结构和套接字的长度.sockaddr必须包含服务端的IP地址和端口号.
  • TCP客户端用connection函数来建立与TCP服务端的连接,因此connection函数是一个客户端使用的函数,如果是TCP套接字,调用connection函数将激发TCP的三次握手过程,只有当建立成功或者是失败时该函数才返回,因此,在连接过程中,程序时阻塞的.
  • 客户程序调用connection内核会确定客户端的IP地址,并且会分配一个临时端口号.作为源端口.
  • 错误信息有以下几种情况
    1.若TCP客户没有收到SYN分节的响应,则会返回ETIMEDOUT错误,举例来说,4.4BSD内核发送一个SYN,如果没有响应,则等待6s再发送一个,如果还没有响应,则等待24秒发送一个,若总共等待了75秒还没有响应则返回ETIMEOUT错误.
    2.若对客户的SYN的响应是RST(复位),则表明该服务器主机,在指定的端口没有进程,等待连接(比如服务器进程未运行),这是一种硬错误,客户一接收到RST则立马返回ECONNREFUSED.
    3.若客户发出的SYN在中间的某个路由器上引发了一个destination unreachable的ICMP错误,该错误会保存在内核中,然后会按照第一种情况来处理,如果,75秒还是没有响应,则返回EHOSTUNREACH
  • 当connection函数返回失败后必须关闭当前套接字描述符,并重新调用socket,然后重新连接.

bind函数

#include<sys/socket.h>
int bind(int sockfd,const struct sockaddr *myaddr,sickle_t addrlen);
  • bind函数通常用于设置本机的地址和端口号,对于客户端来说,不一定必须调用该函数,如果不调用该函数,客户端在和服务端通信的时候,会读取本机的地址和设置一个临时的端口号,和服务器通信。
  • 服务端需要调用该函数,本机的地址通常设置为INADDR_ANY,表示内核自己设置本机IP,通常要明确设置端口号,不设置端口号是很罕见的。bind函数返回的一个常见的错误是:EADDRINUSE(端口地址被占用).

listen函数

#include<sys/socket.h>
int listen(ins sockfd,int backlog);
  • listen函数仅由TCP服务器调用,当socket函数创建一个套接字描述符时,它被假设为一个主动套接字,即它将调用connect函数,listen函数把一个未连接的套接字,转换成一个被动套接字,它指示内核应该接受连接请求,到接字状态从CLOSED状态转换成LISTEN状态.
  • backlog规定了内核应为相应套接字排队的最大连接数.
  • 内核为任何一个给定的监听套接字维护了两个队列:
    (1)未完成连接队列,当客户程序,发送请求连接(第一次握手)到达时,内核会将这个过程放入该队列
    (2)已完成连接队列,当客户程序完成了三次握手时,内核会将未完成队列移到已完成队列中去.以上的处理,是内核处理,服务器的进程无需插手.当服务器进程调用accept时,内核会将已完成队列的对头的信息,返回给进程,如果该队列为空,进程会进入睡眠(阻塞),直到有队列不为空才返回.
  • backlog表示未连接队列和已连接队列之和的最大值,注意!不要将backlog设置为0.

accept函数

#include<sys/socket.h>
int accept(int sockfd,struct sockaddr * clientaddr,socklen_t *addrlen);
  • accept由服务器调用,如果accept返回成功,其返回值是由内核自动生成的一个全新描述符,代表与客户端的TCP连接(此时连接已经完成了,可以进行数据交互了),比如我们要发送数据,则调用write(fd,buffer,strlen(buffer));此处的fd便是由accept返回的,他就是一个连接区分TCP连接的标记(不然服务器怎么知道把数据返回给哪个socket连接).
  • 此函数最多返回三个值,一个是函数的返回值,clidetaddr是一个指针类型的,因此传一个地址过去,clientaddr便会返回客户端的套接字地址结构信息,比如客户端的ip地址和端口号,addrlen表示客户端套接字地址结构的长度,如果对客户端的地址结构不敢兴趣,第二个参数和第三个参数可以传NULL.

总结

本文对tcp套接字的API的各个函数进行了介绍,上面介绍的函数是理解TCP套接字编程的基础,下一篇文章,将会运用本章所介绍的函数,编写一个客户服务端程序.

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

推荐阅读更多精彩内容