我是靠谱客的博主 背后火,这篇文章主要介绍linux网络编程-TCP socket编程模型,现在分享给大家,希望可以做个参考。

1. 编程模型

三次握手 + 四次挥手

2.主要函数说明

字节序转换函数:

复制代码
1
2
3
4
5
#include <arpa/inet.h> uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);

IP转换函数:

复制代码
1
2
3
#include <arpa/inet.h> int inet_pton(int af, const char *src, void *dst);//把字符串的ip转换成32位二进制的整型 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);//把32位二进制的整型转成字符串的ip

sockaddr结构体:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
struct sockaddr { sa_family_t sa_family; /* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ }; //ipv4 struct sockaddr_in { __kernel_sa_family_t sin_family; /* Address family */ __be16 sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr'. */ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)];//填充字节 }; /* Internet address. */ struct in_addr { __be32 s_addr; }; //ipv6 struct sockaddr_in6 { unsigned short int sin6_family; /* AF_INET6 */ __be16 sin6_port; /* Transport layer port # */ __be32 sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ }; struct in6_addr { union { __u8 u6_addr8[16]; __be16 u6_addr16[8]; __be32 u6_addr32[4]; } in6_u; #define s6_addr in6_u.u6_addr8 #define s6_addr16 in6_u.u6_addr16 #define s6_addr32 in6_u.u6_addr32 }; #define UNIX_PATH_MAX 108 struct sockaddr_un { __kernel_sa_family_t sun_family; /* AF_UNIX */ char sun_path[UNIX_PATH_MAX]; /* pathname 类似于有名管道*/ };

socket():

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); domain:   AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址   AF_INET6 与上面类似,不过是来用IPv6的地址   AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用 type:   SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。   SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。   SOCK_SEQPACKET 这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取   SOCK_RAW 这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)   SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数包的顺序 protocol:   0 默认协议 返回值:   成功返回一个新的文件描述符,失败返回-1,设置errno

bind():

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //绑定后,若有用户访问addr地址时,会通过sockfd进行数据传递 sockfd: socket文件描述符 addr: 构造出IP地址加端口号 addrlen: sizeof(addr)长度 返回值: 成功返回0,失败返回-1, 设置errno

listen():

复制代码
1
2
3
4
5
6
7
8
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int listen(int sockfd, int backlog);//让sockfd所指向的socktet具有监听的能力 sockfd: socket文件描述符 backlog: 排队建立3次握手队列和刚刚建立3次握手队列的链接数和(默认为128 )

accept():

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); sockdf: socket文件描述符 addr: 传出参数,返回链接客户端地址信息,含IP地址和端口号 addrlen: 传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小(IPv4或IPv6) 返回值: 成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

connect():

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockdf: socket文件描述符 addr: 传入参数,指定服务器端地址信息,含IP地址和端口号 addrlen: 传入参数,传入sizeof(addr)大小 返回值: 成功返回0,失败返回-1,设置errno

3. 示例代码

server.c

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #define SERVER_PORT 8000 #define MAXLINE 4096 int main(void) { struct sockaddr_in serveraddr, clientaddr; int sockfd, addrlen, confd, len, i; char ipstr[128]; char buf[MAXLINE]; //1.socket sockfd = socket(AF_INET, SOCK_STREAM, 0); //2.bind bzero(&serveraddr, sizeof(serveraddr)); /* 地址族协议IPv4 */ serveraddr.sin_family = AF_INET; /* IP地址 */ serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(SERVER_PORT); bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); //3.listen listen(sockfd, 128); while (1) { //4.accept阻塞监听客户端链接请求 addrlen = sizeof(clientaddr); confd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);//返回的是客户端和服务端专用通道的socket描述符 //输出客户端IP地址和端口号 inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, ipstr, sizeof(ipstr)); printf("client ip %stport %dn", inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, ipstr, sizeof(ipstr)), ntohs(clientaddr.sin_port)); //和客户端交互数据操作confd //5.处理客户端请求 len = read(confd, buf, sizeof(buf)); i = 0; while (i < len) { buf[i] = toupper(buf[i]); i++; } write(confd, buf, len); close(confd); } close(sockfd); return 0; }

client.c

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <netinet/in.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #define SERVER_PORT 8000 #define MAXLINE 4096 int main(int argc, char *argv[]) { struct sockaddr_in serveraddr; int confd, len; char ipstr[] = "192.168.6.254"; char buf[MAXLINE]; if (argc < 2) { printf("./client strn"); exit(1); } //1.创建一个socket confd = socket(AF_INET, SOCK_STREAM, 0); //2.初始化服务器地址 bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; //"192.168.6.254" inet_pton(AF_INET, ipstr, &serveraddr.sin_addr.s_addr); serveraddr.sin_port = htons(SERVER_PORT); //3.链接服务器 connect(confd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); //4.请求服务器处理数据 write(confd, argv[1], strlen(argv[1])); len = read(confd, buf, sizeof(buf)); write(STDOUT_FILENO, buf, len); //5.关闭socket close(confd); return 0; }

makefile

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
all:server client server:server.c gcc $< -o $@ client:client.c gcc $< -o $@ .PHONY:clean clean: rm -f server rm -f client

最后

以上就是背后火最近收集整理的关于linux网络编程-TCP socket编程模型的全部内容,更多相关linux网络编程-TCP内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部