TCP基本套接字编程笔记(一)套接字函数

使用TCP套接字编程可以实现基于TCP/IP协议的面向连接的通信,它分为服务端(Server)和客户端(Client)两个部分,具体流程图如下所示:


流程图.png

现在就基本套接字函数做学习笔记:

socket()函数

为了执行I/O,无论是服务端还是客户端,首先必须调用socket()函数,产生TCP套接字,作为TCP通信的传输端点。

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

该函数调用成功,则返回一个小的非负的整数值,失败则返回-1;

family参数指明协议族,它的值常用为:

family=AF_INET;//IPv4协议;
family=AF_INET6;//IPv6协议;
family=AF_ROUTE;//路由套接口。

type参数指明产生套接字的类型,它的值常用为:

type=SOCK_STREAM;//字节流套接口,TCP常用的形式;
type=SOCK_DGRAM;//数据报套接口,UDP常用的形式 ;
type=SOCK_RAW;//原始套接口

protocol参数是协议标志,一般在调用socket()函数时将其设置为0。(但如果是原始套接字,就需要为其指定一个常值)

//eg:调用socket()函数 
#include <sys/socket.h>
...
int sockfd;
//crteate socket
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
       //handle exception
       ...
}

bind()函数

绑定函数的作用就是为调用socket()函数产生的套接字分配一个本地协议地址,建立地址与套接字的对于关系。

#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *server,socklen_len addrlen);

该函数调用成功返回0,若出错则返回-1,并置错误号errno;

sockfd参数是套接字函数返回的套接字描述符;

server参数是指向特定于协议的地址结构的指针,指定用于通信的本地协议地址;

addrlen参数是指定该套接字地址结构的长度;

//eg: 调用bind()函数
#include <sys/socket.h>
...
int sockfd;
int port = 1234;//bind 的端口号是1234
struct sockaddr_in server;
...
//对服务器的地址结构初始化赋值,IP地址是一个通配地址,由内核选择。
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
//调用bind()函数将描述符sockfd与server套接字地址结构中的协议地址绑定 
if(bind(sockfd,(struct sockaddr *)&server,sizeof(server)) == -1)
{
       //handle exception
       //如果调用失败,则进行异常处理
       ...
}
...

listen()函数

监听函数的作用就是将未连接的套接字转换成被动套接字,使它处在监听模式下,指示内核应接受发向该套接字的连接请求。

#include <sys/socket.h>
int listen(int sockfd,int backlog);

该函数调用成功返回0,若出错则返回-1,并置errno值;

sockfd参数是要设置的描述符;

backlog参数规定了请求队列中的最大连接数;

//eg:调用listen()函数
#include <sys/socket.h>
...
int sockfd;
int BACKLOG = 5;//设置监听的最大连接数为5
...
//调用listen()函数,将sockfd描述符设置为监听描述符
if(listen(sockfd,BACKLOG) == -1)
{
       //handle exception
       //如果调用失败,则进行异常处理
       ...
}  
...

accept()函数

接受函数的作用就是使服务器接受客户端的连接请求。

#include <sys/socket.h>
int accept(int listenfd,struct sokaddr *client,socklen_t *addrlen);

该函数调用成功后,返回三个值:

(1):accept()函数的返回值,已连接套接字描述符;
(2):client参数参会客户端的协议地址,包括IP地址和端口号等; 
(3):addrlen参数返回客户端地址结构的大小。

如果调用失败则返回-1,并置errno值。

listenfd参数是由sockfd()函数产生的套接字描述符,在调用accept()函数前,已经调用listen()函数将此套接字变成了监听套接字;

client参数是用来返回连接对方的套接字地址结构;

addrlen参数是用来返回连接对方的套接字的结构长度。

//eg:调用accept()函数
#include <sys/socket.h>
...
int listenfd,connfd;//定义两个套接字描述符,监听套接字描述符和已连接套接字描述符
struct sockaddr_in client;
socklen_t addrlen;
addrlen=sizeof(client);//得到client当前的长度
...
//调用accept()函数,接收连接请求,返回已连接套接字描述符
connfd = accept(listenfd,(struct sockaddr *)&client,&addrlen);
if(connfd == -1)
{
       //handle exception
       //如果调用失败,则进行异常处理
       ...
}
...

connect()函数

连接函数的作用就是让TCP客户端使用来配置套接字,建立一个与TCP服务器的连接。(激发TCP的三次握手过程)

#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

该函数调用成功后返回0,若出错则返回-1;

sockfd参数是有sockd()函数返回的套接字描述符;

addr参数是指向服务器的套接字地址结构的指针;

addrlen参数是该套接字地址结构的大小

//eg:调用connect()函数
#include <sys/socket.h>
...
int sockfd;
struct sockaddr_in server;
...
bzero(&server,sizeof(server));//为套接字地址结构server设置初始值0
//位套接字地址结构中的成员复制,客户端要建立链接的服务器IP地址为127.0.0.1,端口号为1234.
server.sin_family = AF_INET;
server.sin_port = htons(1234);
server.sin_addr.s.addr = inet_addr("127.0.0.1");
//调用connect()函数与服务器建立连接
if(connect(sockfd,(struct sockaddr *)&server,sizeof(server)) ==
-1)
{
       //handle exception
       //如果调用失败,则进行异常处理
       ...
}
...

数据传输函数:write()和read()函数

当服务器和客户端的连接建立起来后,就可以进行双向的数据传输了。

write()和read()函数

write()函数用于数据的发送:

#include <unistd.h>
int write(int sockfd,char *buf,int len);

该函数调用成功返回大于0的整数,也就是发送的字节数,若出错则返回-1;

buf参数是指向一个用于发送信息的数据缓冲区;

len参数是指明传送数据缓冲区的大小。

read()函数用于数据的接收

#include <unistd.h>
int read(int sockfd,char *buf,int len);

该函数调用成功返回大于0的整数,也就是发送的字节数,若出错则返回-1;

buf参数是指向一个用于接收信息的数据缓冲区;

len参数是指明接收数据缓冲区的大小。

//eg:调用read()函数
#include <unistd.h>
#include <sys/sockfd.h>
#define MAXDATASIZE 100;//定义接收信息的数据缓冲区的长度 
...
int num,connfd;
char buf[MAXDATASIZE];
...
//接收数据,整数num返回接收的字节数
if(((num = read(connfd,buf,MAXDATASIZE)) > 0))
{
       //handle data
       //处理接收到的数据
       ...
}
...

close()函数

关闭函数的作用就是关闭套接字,并立即返回到进程。

#include <unistd.h>
int close(int sockfd);

下一章开始介绍基本TCP套接字编程实例。

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

推荐阅读更多精彩内容