加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux下的TCP Socket通信

发布时间:2020-12-13 23:46:53 所属栏目:Linux 来源:网络整理
导读:一、 socket函数 1、头文件: #include sys/types.h /* See NOTES */ #include sys/socket.h 2、函数原型: int socket(int domain,int type,int protocol); socket函数类似于 open,用来打开一个网络连接,如果成功则返回一个网络文件描述符( int类型),

一、socket函数

1、头文件:

#include <sys/types.h> /* See NOTES */

#include <sys/socket.h>

2、函数原型:

int socket(int domain,int type,int protocol);

socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。

dimain:域,网络域,网络地址范围(IPV4或IPV6等),也就是协议簇

type:指定套接字类型:SOCK_STREAM(TCP网络)、SOCK_DGRAM(UDP)、SOCK_SEQPACKET

protocol:指定协议,如果指定0,表示使用默认的协议

3、函数形参:

3.1、domain:(域)

AF_INET     ?ip
AF_INET6    ipv6

AF_PACKET ? ? ? ??packet ? ? ? ??低级数据包接口

PF_PACKET   不懂,待了解

PF_INET     ?待了解(AF开头的表示地址族,PF开头的表示协议族,协议族包含多个地址族,但是当前这种还从未实现,而在<sys/socket.h>中PF的值总是与AF的值相等的)

3.2、type:(套接字类型):

SOCK_RAW   ?  原始套接字 ?   ——>使用原始套接字时候调用,原始套接字也就是链路层协议

SOCK_STREAM   ?字节流套接字   ?——>提供顺序,可靠,双向,基于连接的字节流。 可以支持带外数据传输机制。例如:TCP协议、FTP协议

SOCK_DGRAM ? ? ? ? 数据报套接字   ?——>支持数据报(无连接,不可靠的固定最大长度的消息)例如:UDP协议

SOCK_SEQPACKET ? 有序分组套接字 ? ?——>为固定最大长度的数据报提供有序,可靠,双向连接的数据传输路径; 消费者需要利用每个输入系统调用读取整个分组

3.3、protocol(协议):

IPPROTO_IP     ? IP传输协议

IPPROTO_TCP    ? TCP传输协议

IPPROTO_UDP   ? ? UDP协议

IPPROTO_SCTP   ? ?SCTP传输协议

IPPROTO_ICMP ? ? ? ? ?ICMP协议

IPPROTO_IGMP   ? ?IGMP协议

一般情况下IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP协议用的最多,UDP协议protocol就取IPPROTO_UDP,TCP协议protocol就取IPPROTO_TCP;一般情况下,我们让protocol等于0就可以,系统会给它默认的协议。但是要是使用raw socket协议,protocol就不能简单设为0,要与type参数匹配.

4、返回值:

成功时返回一个小的非负整数值,他与文件描述符类似,我们称为套接字描述符,简称sockfd。失败,则返回-1。

5、例子:

/*---------------------创建一个监听socket-------------------*/

??? if ((listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1)

??? {

??????? perror("socket() errorn");

??????? exit(1);

}

二、bind函数

1、头文件:

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>

2、函数原型:

int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

服务端套接字绑定自己的IP地址与端口号,客户端那边可以不写,内核会给它分配一个临时的端口。

3、函数形参:

3.1、sockfd:服务器或者客户端自己创建的socket

3.2、addr:服务器或者客户端自己的地址信息(协议族、IP、端口号)

3.3、addrlen:服务器或者客户端自己的地址信息的长度

4、返回值:

绑定成功,返回0,失败返回-1

5、例子:

??? /*---------------------绑定IP和端口bind----------------------*/

??? bzero(&server,sizeof(server));

??? server.sin_family = AF_INET;

??? server.sin_port = htons(port);

??? server.sin_addr.s_addr = inet_addr(ip);

?

??? if (bind(listenfd,(struct sockaddr *)&server,sizeof(server)) == -1)

??? {

??????? perror("bind() errorn");

??????? exit(1);

??? }

三、connect函数

1、头文件:

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>

2、函数原型:

int connect(int sockfd,socklen_t addrlen);

TCP客户端通过connect函数与服务端连接,进行通信。

3、函数形参:

3.1、sockfd(客户端自己创建的sock)

3.2、addr(服务端地址族、服务端IP地址、服务端端口号)

3.3、addrlen(服务端地址字节长度)

4、返回值:

连接成功,返回0,连接失败,返回-1

5、例子:

struct sockaddr_in client;

addrlen = sizeof(client);

??????? if ((connetfd = accept(listenfd,(struct sockaddr *)&client,&addrlen)) == -1)

??????? {

??????????? perror("accept() errorn");

??????????? exit(1);

??????? }

接下来给出一个大例子,tcp——socket套接字通信,结合sqlite3数据库操作

#include <stdio.h>

#include <stdlib.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <unistd.h>

#include <string.h>

?

int main()

{

??? struct sockaddr_in server;

??? struct sockaddr_in client;

??? int listenfd,connetfd;

??? char ip[20];

??? int port;

??? int addrlen;

??? char rebuf[100];

??? char wrbuf[100];

??? char tmp[100];

??? int revlen;

??? /*---------------------创建一个监听socket-------------------*/

??? if ((listenfd = socket(AF_INET,0)) == -1)

??? {

??????? perror("socket() errorn");

??????? exit(1);

??? }

?

??? /*----------------------输入要监听的IP和端口----------------------*/

??? printf("Please input the ip:n");

??? scanf("%s",ip);

??? printf("Please input the port:n");

??? scanf("%d",&port);

?

??? /*---------------------绑定IP和端口bind----------------------*/

??? bzero(&server,sizeof(server));

??? server.sin_family = AF_INET;

??? server.sin_port = htons(port);

??? server.sin_addr.s_addr = inet_addr(ip);

?

??? if (bind(listenfd,(struct sockaddr *)&server,sizeof(server)) == -1)

??? {

??????? perror("bind() errorn");

??????? exit(1);

??? }

??? /*----------------------开始监听listen-------------------*/

??? if (listen(listenfd,20) == -1)

??? {

??????? perror("listen() errorn");

??????? exit(1);

??? }

??? int client_pid = 0;

??? while (1)

??? {

??????? /*----------------------accept------------------*/

??????? addrlen = sizeof(client);

??????? if ((connetfd = accept(listenfd,(struct sockaddr *)&client,&addrlen)) == -1)

??????? {

??????????? perror("accept() errorn");

??????????? exit(1);

??????? }

??????? /*---------------------show client---------------*/

??????? printf("connect successful!n");

??????? printf("the client ip is %s,port is %dn",inet_ntoa(client.sin_addr),ntohs(port));

??????? client_pid = fork();

??????? if (client_pid == 0)

??????? {

??????????? //子进程

??????????? close(listenfd); //关闭监听请求

??????????? /*----------------------read and write----------*/

??????????? int serial = 0;

??????????? while (1)

??????????? {

??????????????? bzero(rebuf,sizeof(rebuf));

??????????????? revlen = read(connetfd,rebuf,sizeof(rebuf));

??????????????? if ((memcmp("bye",3)) == 0)

??????????????? {

??????????????????? printf("Bye-bye then close the connect...n");

??????????????????? break;

??????????????? }

??????????????? bzero(wrbuf,sizeof(wrbuf));

??????????????? bzero(tmp,sizeof(tmp));

??????????????? sprintf(tmp,"%d",serial);

??????????????? strcat(tmp,rebuf);

??????????????? bcopy(tmp,wrbuf,strlen(tmp));

??????????????? write(connetfd,sizeof(wrbuf));

??????????????? rebuf[revlen] = ;

??????????????? printf("the info from client is:%sn",rebuf);

??????????????? serial++;

??????????? }

??????????? return 0;

??????? }

??????? close(connetfd); //父进程关闭连接请求

??? }

??? return 0;

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读