socket()
int socket(int domain, int type, int protocol);
参数:
-
domain: 即协议域,又称为协议族(family)。
-
常用的协议组有:
-
AF_INET(ipv4地址(32位的)与端口号(16位的)的组合)
-
AF_INET6( IPv6 的地址族)
-
AF_LOCAL(或称AF_UNIX,Unix域socket)(用一个绝对路径名作为地址)
-
AF_ROUTE
-
-
type: 指定socket类型。
- 常用的socket类型有:
- SOCK_STREAM
- SOCK_DGRAM
- SOCK_RAW
- SOCK_PACKET
- SOCK_SEQPACKET等等
- 常用的socket类型有:
-
protocol:指定协议。
-
常用的协议有:
- IPPROTO_TCP(TCP传输协议)
- IPPTOTO_UDP(UDP传输协议)
- IPPROTO_SCTP(STCP传输协议)
- IPPROTO_TIPC等(TIPC传输协议)
-
-
Return Value 成功產生socket時,會返回該socket的檔案描述符(socket file descriptor),我們可以透過它來操作socket。若socket創建失敗則會回傳-1(INVALID_SOCKET)。
举例
r->m_sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind() : 赋予地址和端口
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数
-
sockfd: 即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
-
addr: 一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址
-
addrlen:地址的长度。
通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。
listen()
int listen(int sockfd, int backlog);
- 参数:
- sockfd::即socket描述字,唯一的id。
- backlog:相应socket可以排队的最大连接个数。
connect()
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 参数:
- sockfd:socket描述符。
- addr:服务器的socket地址。
- addrlen:socket地址的长度
accept()取接收请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 参数:
- sockfd:服务器的socket描述字。
- addr:指向struct sockaddr *的指针,用于返回客户端的协议地址。
- addrlen:协议地址的长度。
send()
int send(int sockfd, const void *msg, int len, int flags);
- 参数:
- sockfd:想要发送数据的套接字描述符。
- msg:指向发送的消息数据的指针。
- flags:一般设置为0.
recv()
int recv(int sockfd, void *buf, int len, unsigned int flags);
- 参数:
- sockfd:要读的套接字描述符。
- buf:读取数据的缓冲区。
- len:缓冲区的最大长度。
- flags:一般设置为0.
sendto()
int sendto(int sockfd, const void *msg, int len, unsigned int flags,
const struct sockaddr *to, int tolen);
- 参数
- to 是个指向数据结构 struct sockaddr 的指针,它包含了目的地的 IP 地址和端口信息。
- tolen 可以简单地设置为 sizeof(struct sockaddr)。
Server Code
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
std::cout << "socket 服务端开始运行" << std::endl;
int result = -1;
// SOCK_STREAM: 面向连接的数据传输方式
int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 将套接字 和IP,端口绑定
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1234);
result = bind(serv_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (result < 0) {
return 0;
}
// 开始进入监听
listen(serv_sock, 20);
// 接收客户端请求
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock = accept(serv_sock, (struct sockaddr *) &clnt_addr, &clnt_addr_size);
// 向客户端发送数据
auto toClientStr = "这是我给你的积极响应";
write(clnt_sock, toClientStr, strlen(toClientStr));
return 0;
}
Client Code
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
std::cout << "客户端开始运行: " << std::endl;
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1234);
connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
// read data;
char buffer[256];
read(sock, buffer, sizeof(buffer) - 1);
std::cout << " buffer : is " << buffer << std::endl;
//关闭套接字
close(sock);
return 0;
}