欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

TCP 基本套接字编程说明 (a) 套接字功能

最编程 2024-07-09 14:51:29
...

使用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套接字编程实例。

推荐阅读