学习视频链接
目录
1、TCP
面向连接的,可靠数据包传输。对于不稳定的网络层,采取完全弥补的通信方式。丢包重传。
优点:稳定 (数据流量稳定、速度稳定、顺序)
缺点:传输速度慢。相率低。开销大
使用场景:数据的完整型要求较高,不追求效率。大数据传输、文件传输

2、UDP
无连接的,不可靠的数据报传递。对于不稳定的网络层,采取完全不弥补的通信方式。默认还原网络状况
优点:传输速度块。相率高。开销小
缺点:不稳定 (数据流量。速度。顺序)
使用场景:对时效性要求较高场合。稳定性其次。游戏、视频会议、视频电话。腾讯、华为、阿里--- 应用层数据校验协议, 弥补 udp 的不足

recv() / send() 只能用于 TCP 通信。替代 read、write
accpet():--- Connect(); ---被舍弃
server:
lfd = socket(AF_INET, STREAM, 0);
SOCK_DGRAM ---报式协议
bind();
listen(); --- 可有可无
while(1) {
read(cfd, buf, sizeof) ---被替换 ---recvfrom() ---涵盖accept传出地址结构体
小 -- 大
write():---被替换--- sendto()
}
close();
client:
connfd = socket(AF_INET, SOCK_DGRAI, 0);
sendto(‘服务器的地址结构’, 地址结构大小)
recvfrom()
写到屏幕
close();
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
sockfd: lfd
buf: 缓冲区地址
len: 缓神区大小
flags: 0
src_addr: (struct sockaddr *) &addr 传出。对端地址结构
addrlen: 传入传出
返回值: 成功接收数据字节数。失败: -1 errn。 0: 对端关闭
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
sockfd: 套接字
buf: 存储数据的缓冲区
len: 数据长度
flags: 0
src_addr: (struct sockaddr *) &addr 传入。目标地址结构
addrlen: 地址结构长度
返回值:成功接收数据字节数。失败 -1 errno
server.c
- #include
- #include
- #include
- #include
- #include
-
- #define SERV_PORT 8000
-
- int main(void)
- {
- struct sockaddr_in serv_addr, clie_addr;
- socklen_t clie_addr_len;
- int sockfd;
- char buf[BUFSIZ];
- char str[INET_ADDRSTRLEN];
- int i, n;
-
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-
- bzero(&serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(SERV_PORT);
-
- bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
-
- printf("Accepting connections ...\n");
- while (1) {
- clie_addr_len = sizeof(clie_addr);
- n = recvfrom(sockfd, buf, BUFSIZ, 0, (struct sockaddr *)&clie_addr, &clie_addr_len);
- if (n == -1) {
- perror("recvfrom error");
- }
-
- printf("received from %S at PORT %d\n",
- inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
- ntohs(clie_addr.sin_port));
-
- for(i = 0; i < n; i++) {
- buf[i] = toupper(buf[i]);
- }
-
- n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr));
- if (n == -1) {
- perror("sendto error");
- }
- }
-
- close(sockfd);
-
- return 0;
- }
client.c
- #include
- #include
- #include
- #include
- #include
-
- #define SERV_PORT 8000
-
- int main(int argc, char *argv[])
- {
- struct sockaddr_in servaddr;
- int sockfd, n;
- char buf[BUFSIZ];
-
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
- servaddr.sin_port = htons(SERV_PORT);
-
- bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
-
- while (fgets(buf, BUFSIZ, stdin) != NULL) {
- n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
- if (n == -1)
- perror("sendto error");
-
- n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0); //NULL:不关心对端信息
- if (n == -1)
- perror("recvfrom error");
-
- write(STDOUT_FILENO, buf, n);
- }
-
- close(sockfd);
-
- return 0;
- }

pipe:易用性是最强的
fifo:没有血缘关系进程之间的通信
mmap:没有血缘关系进程之间的通信,可以反复读取
信号:开销最小
本地套接字 (domain):稳定性最好的(CS 模型)
1、int socket(int domain, int type, int protocol);
参数:
domin: AF_INET 变为 AF_UNIX/AF_LOCAL
type: SOCK_STREAM/SOCK_DGRAM 都可以
2、地址结构 socke_in -> sockaddr_un
struct sockaddr_in srv_addr; -> struct sockaddr_un srv_addr;
srv_addr.sin_family = AF_INET; -> srv_adrr.sun_family = AF_UNIX;
srv_addr.sin_port = htons(8888); -> strcpy(srv_addr.sun_path, "srv.socket")
srv_addr.sin_addr.s_addr = hton(INADDR_ANY);
bind(fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); -> bind(fd, (struct sockaddr *)&srv_addr, offsetof(struct sockaddr_un, sun_path) + strlen("srv.socket"));
sockaddr_un

sockaddr 数据结构

bind 函数创建出来的这个文件,是一个伪文件

服务端
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #include "wrap.h"
-
- #define SERV_ADDR "serv.socket"
-
- int main(void)
- {
- int lfd, cfd, len, size, i;
- struct sockaddr_un servaddr, cliaddr;
- char buf[4096];
-
- lfd = Socket(AF_UNIX, SOCK_STREAM, 0);
-
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sun_family = AF_UNIX;
- strcpy(servaddr.sun_path, SERV_ADDR);
-
- len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path); /* servaddr total len */
-
- unlink(SERV_ADDR); /* 确保bind之前serv.sock文件不存在,bind会创建该文件 */
- Bind(lfd, (struct sockaddr *)&servaddr, len); /* 参3不能是sizeof(servaddr) */
-
- Listen(lfd, 20);
-
- printf("Accept ...\n");
- while (1) {
- len = sizeof(cliaddr); //AF_UNIX大小+108B
-
- cfd = Accept(lfd, (struct sockaddr *)&cliaddr, (socklen_t *)&len);
-
- len -= offsetof(struct sockaddr_un, sun_path); /* 得到文件名的长度 */
- cliaddr.sun_path[len] = '\0'; /* 确保打印时,没有乱码出现 */
-
- printf("client bind filename %s\n", cliaddr.sun_path);
-
- while ((size = read(cfd, buf, sizeof(buf))) > 0) {
- for (i = 0; i < size; i++)
- buf[i] = toupper(buf[i]);
- write(cfd, buf, size);
- }
- close(cfd);
- }
- close(lfd);
-
- return 0;
- }
客户端
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #include "wrap.h"
-
- #define SERV_ADDR "serv.socket"
- #define CLIE_ADDR "clie.socket"
-
- int main(void)
- {
- int cfd, len;
- struct sockaddr_un servaddr, cliaddr;
- char buf[4096];
-
- cfd = Socket(AF_UNIX, SOCK_STREAM, 0);
-
- bzero(&cliaddr, sizeof(cliaddr));
- cliaddr.sun_family = AF_UNIX;
- strcpy(cliaddr.sun_path,CLIE_ADDR);
-
- len = offsetof(struct sockaddr_un, sun_path) + strlen(cliaddr.sun_path); /* 计算客户端地址结构有效长度 */
-
- unlink(CLIE_ADDR);
- Bind(cfd, (struct sockaddr *)&cliaddr, len); /* 客户端也需要bind, 不能依赖自动绑定*/
-
- bzero(&servaddr, sizeof(servaddr)); /* 构造server 地址 */
- servaddr.sun_family = AF_UNIX;
- strcpy(servaddr.sun_path, SERV_ADDR);
-
- len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path); /* 计算服务器端地址结构有效长度 */
-
- Connect(cfd, (struct sockaddr *)&servaddr, len);
-
- while (fgets(buf, sizeof(buf), stdin) != NULL) {
- write(cfd, buf, strlen(buf));
- len = read(cfd, buf, sizeof(buf));
- write(STDOUT_FILENO, buf, len);
- }
-
- close(cfd);
-
- return 0;
- }
对比 本地套 和 网络套
