[TOC]
在TCP/IP协议中“IP地址 + TCP或UDP端口号”作为唯一标识网络通讯中的一个进程,“IP + 端口号”就称为socket。在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么两个socket组成的socket pair就唯一标识一个连接。
## 相关函数
与网络通信相关的几个函数:
* [socket](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html):创建一个socket;
* [bind](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html#):将socket绑定到端口上;
* [listen](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html#): 开始监听端口;
* [accept](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html#):取出等待链接队列中的首元素;
* [connect](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html#):与指定ip端口创建连接;
* [close](https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html#):关闭连接;
## 创建socket
```c++
// 创建socket并监控指定ip和端口
static int create_socket(const char* ip, int port) {
int sock = socket(AF_INET, SOCK_STREAM, 0); // 创建socket
if (sock < 0) {
perror("failed to create socket");
return -1;
}
sockaddr_in local; // 设置监听端口配置
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = inet_addr(ip);
// 将socket绑定到端口上
if (bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
close(sock);
perror("failed to bind socket");
return -1;
}
// socket开始监听端口
static int BACK_LOG = 10;
if (listen(sock, BACK_LOG) < 0) {
close(sock);
perror("failed to listen socket");
return -1;
}
return sock;
}
```
## 建立连接
server 端:
```c++
#include <algorithm>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
int main(int argc, char** argv) {
if (argc != 3) {
return -1;
}
int sock = create_socket(argv[1], atoi(argv[2]));
if (sock < 0) {
printf("failed to create socket");
return -1;
}
printf("start to listen ip[%s:%s]\n", argv[1], argv[2]);
sockaddr_in link;
socklen_t sz = sizeof(link);
int fd = accept(sock, (struct sockaddr*)&link, &sz);
if (fd < 0) {
perror("failed to accept");
close(sock);
return -1;
}
printf("fd = %d\n", fd);
static const int MAX_READ_SIZE = 1024;
char buffer[MAX_READ_SIZE];
while (1) {
ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
printf("recv message: %s", buffer);
if (s > 0) {
const char* msg = "HTTP/1.0 200 OK\n";
write(fd, msg, strlen(msg));
} else if (s == 0) {
printf("fd[%d] quit\n", fd);
close(fd);
break;
} else {
perror("failed to read fd");
close(fd);
break;
}
}
printf("sock[%d] quit\n", sock);
close(sock);
return 0;
}
```
client端:
```c++
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc != 3) {
printf("FATAL: no host or port");
exit(1);
}
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("failed to create socket");
return 1;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(argv[1]);
server.sin_port = htons(atoi(argv[2]));
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("failed to connect");
exit(1);
}
while (1) {
printf("send message: ");
fflush(stdout);
static const int MAX_BUFF_SIZE = 1024;
char buffer[MAX_BUFF_SIZE];
ssize_t s = read(0, buffer, sizeof(buffer) - 1);
if (s > 0) {
buffer[s] = '\0';
}
write(sock, buffer, strlen(buffer));
s = read(sock, buffer, sizeof(buffer) - 1);
if(s > 0) {
buffer[s - 1] = 0;
printf("server feeback: %s\n", buffer);
}
}
close(sock);
return 0;
}
```
## 相关文献
- [opengroup-socket](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html)
- 目录
- 基础知识
- 1、变量和基础类型
- 1.1、内置类型
- 1.2、变量
- 1.3、复合类型
- 1.4、类型修饰符
- 1.5、类型处理
- 1.6、自定义结构
- 1.7、数组
- 2、表达式和语句
- 2.1、运算符
- 2.2、语句
- 3、函数
- 1、语法相关
- 2、资源管理
- 3、面向对象
- 4、模板与泛型编程
- Problem01:判断类中是否包含函数
- Problem02:解析函数的参数类型
- 5、系统库
- Problem01:多线程维护最大值
- Problem02:介绍一下strcpy、strncpy、memcpy、memmove
- Problem03:介绍一下网络编程
- Problem04:select、poll、epoll的区别
- 未整理
- Problem11:实现在main函数前、后执行的函数
- Problem12:可变参函数的实现
- Problem13:全局变量初始化顺序问题
- Problem14:介绍一下隐式转换
- Problem07:实现一个不能被拷贝的类
- Problem08:实现一个只能通过动态、静态分配的类
- 开源项目
- redis
- 第一部分 数据结构与对象
- redis 底层数据结构
- redis 对象
- taskflow
- 数据结构
- Executor
