在C++中,Windows环境下实现socket通信的客户端与服务端的流程如下:
用于创建套接字的函数
#include
SOCKET socket(int af, int type, int protocol);
参数说明:
返回值:
可能遇到的问题:
用于将套接字与特定的IP地址和端口号绑定。具体定义如下:
#include
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
返回值:
可能遇到的问题:
listen()函数用于监听来自客户端的连接请求。它是TCP服务器端套接字的一个函数,用于设置套接字为监听模式,以便接受客户端的连接请求。
#include
int listen(int sockfd, int backlog);
参数:
返回值:
可能遇到的问题:
#include
int connect(
SOCKET s,
const struct sockaddr *name,
int namelen
);
参数说明:
s
:一个有效的套接字描述符,由socket()函数创建。name
:指向一个sockaddr结构的指针,该结构包含了要连接的服务器的地址信息。namelen
:name参数指向的结构的大小(以字节为单位)。返回值:
可能遇到的问题:
accept()函数用于接受一个已连接的客户端请求。它是在服务器端使用的,用于从已完成连接队列中取出一个连接请求,并创建一个新的套接字与客户端进行通信。
#include
#include
#include
#include
SOCKET accept(
SOCKET s,
struct sockaddr *addr,
int *addrlen
);
参数说明:
返回值:
可能遇到的问题:
#include
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数说明:
返回值:
可能遇到的问题:
示例
#include
#include
#include
#include
#pragma comment(lib, "Ws2_32.lib")
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(8888);
bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
listen(listenSocket, 5);
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(listenSocket, &readfds);
while (1) {
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
int ret = select(0, &readfds, NULL, NULL, &timeout);
if (ret == SOCKET_ERROR) {
printf("select error: %d", WSAGetLastError());
break;
} else if (ret == 0) {
printf("select timeout");
continue;
}
for (int i = 0; i < listenSocket + 1; i++) {
if (FD_ISSET(i, &readfds)) {
if (i == listenSocket) {
sockaddr_in clientAddr;
int clientAddrLen = sizeof(clientAddr);
SOCKET clientSocket = accept(listenSocket, (SOCKADDR*)&clientAddr, &clientAddrLen);
FD_SET(clientSocket, &readfds);
printf("new connection: %d", clientSocket);
} else {
char buffer[1024];
int recvLen = recv(i, buffer, sizeof(buffer) - 1, 0);
if (recvLen <= 0) {
closesocket(i);
FD_CLR(i, &readfds);
printf("connection closed: %d", i);
} else {
buffer[recvLen] = '\0';
printf("received from %d: %s", i, buffer);
}
}
}
}
}
closesocket(listenSocket);
WSACleanup();
return 0;
}
send()函数用于发送数据
#include
#include
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数说明:
返回值:
可能遇到的问题:
用于接收从指定的socket发送过来的数据
#include
int recv( SOCKET s, char *buf, int len, int flags);
参数说明:
返回值:
可能遇到的问题:
#include
#include
#pragma comment(lib, "ws2_32.lib") // Winsock Library
#define BUF_SIZE 100
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 1234
int main() {
WSADATA wsaData;
SOCKET hServSock, hClntSock;
char buffer[BUF_SIZE];
int strLen;
SOCKADDR_IN servAddr, clntAddr;
int clntAddrSize;
// 初始化Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed.\n";
return -1;
}
// 创建套接字
hServSock = socket(AF_INET, SOCK_STREAM, 0);
if (hServSock == INVALID_SOCKET) {
std::cerr << "Socket creation failed.\n";
return -1;
}
// 绑定套接字
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
servAddr.sin_port = htons(SERVER_PORT);
if (bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
std::cerr << "Bind failed.\n";
return -1;
}
// 监听套接字
if (listen(hServSock, 5) == SOCKET_ERROR) {
std::cerr << "Listen failed.\n";
return -1;
}
// 接受客户端的连接请求
clntAddrSize = sizeof(clntAddr);
hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &clntAddrSize);
if (hClntSock == INVALID_SOCKET) {
std::cerr << "Accept failed.\n";
return -1;
}
// 接收并打印数据
while ((strLen = recv(hClntSock, buffer, BUF_SIZE, 0)) != 0) {
buffer[strLen] = '\0';
std::cout << "Received: " << buffer << std::endl;
}
// 关闭套接字
closesocket(hClntSock);
closesocket(hServSock);
WSACleanup();
return 0;
}
#include
#include
#pragma comment(lib, "ws2_32.lib") // Winsock Library
#define BUF_SIZE 100
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 1234
int main() {
WSADATA wsaData;
SOCKET hSocket;
char buffer[BUF_SIZE];
int strLen;
SOCKADDR_IN servAddr;
// 初始化Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed.\n";
return -1;
}
// 创建套接字
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET) {
std::cerr << "Socket creation failed.\n";
return -1;
}
// 设置服务器地址结构体
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
servAddr.sin_port = htons(SERVER_PORT);
// 连接到服务器
if (connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
std::cerr << "Connect failed.\n";
return -1;
}
// 发送数据
while (true) {
std::cin >> buffer;
send(hSocket, buffer, strlen(buffer), 0);
}
// 关闭套接字
closesocket(hSocket);
WSACleanup();
return 0;
}
g++ server.cpp -o server -lws2_32
g++ client.cpp -o client -lws2_32
在C语言的Linux环境下,实现socket通信以实现进程间通信,可以分为以下几个步骤:
需要包含头文件
、
和
。然后,使用socket()
函数创建一个socket
#include
#include
#include
int main() {
int server_sockfd;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
}
使用bind()
函数将socket与指定的地址和端口绑定
#include
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
使用listen()
函数开始监听客户端的连接请求
listen(server_sockfd, 5);
使用connect()函数用于建立与指定IP地址和端口号的服务器之间的连接
#include
#include
#include
#include
#include
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
sockfd
:套接字描述符,由socket()函数创建。addr
:指向目标服务器的地址结构体指针,通常使用struct sockaddr_in
来表示IPv4地址。addrlen
:地址结构体的大小,对于struct sockaddr_in
,其大小为sizeof(struct sockaddr_in)
。返回值:
errno
获取错误码。服务端使用accept()
函数接受客户端的连接请求,然后使用send()
和recv()
函数进行数据的发送和接收。
#include
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
char buffer[1024];
send(client_sockfd, "Hello, client!", strlen("Hello, client!"), 0);
recv(client_sockfd, buffer, sizeof(buffer), 0);
#include
#include
#include
#include
int main() {
// 创建socket
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
// 定义sockaddr_in结构体
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888); // 端口号
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP地址
// 绑定socket
bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
// 监听socket
listen(server_fd, 5);
// 接受客户端连接
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_addr_len);
// 向客户端发送数据
char msg[] = "Hello, client!";
send(client_fd, msg, strlen(msg), 0);
// 关闭socket
close(client_fd);
close(server_fd);
return 0;
}
#include
#include
#include
#include
#include
int main() {
// 创建socket
int client_fd = socket(AF_INET, SOCK_STREAM, 0);
// 定义sockaddr_in结构体
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888); // 端口号
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // IP地址
// 连接服务器
connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
// 接收服务器发送的数据
char buffer[1024] = {0};
recv(client_fd, buffer, sizeof(buffer), 0);
printf("Received from server: %s\n", buffer);
// 关闭socket
close(client_fd);
return 0;
}
Domain Socket,也称为UNIX Domain Sockets (UDS),是一种在同一台主机上的进程间通信(IPC)机制。不同于网络套接字使用TCP或UDP协议通过IP地址和端口号进行通信,Domain Socket使用特殊的文件系统来进行通信。以下是关于Domain Socket的一些详细说明:
综上 ,Domain Socket作为一种高效的本地通信方式,它不需要指定IP地址和端口号,而是通过文件系统路径来进行识别和访问。这种通信方式在本地进程间传递信息时提供了一种快速且稳定的方法。
在这种通信方式中,一个进程创建一个Unix域套接字,并将其绑定到一个文件系统中的路径。这个路径就像一个特殊的文件,可以作为通信的端点。其他进程可以通过打开这个特殊文件来连接到该套接字,从而实现进程间的通信。
Domain Socket通信是在本地进行的,所以无法通过网络抓包工具(如Wireshark)在网络接口卡上捕获到相关数据。如果需要查看或分析Domain Socket通信数据,可以使用其他方法,如在程序中添加日志记录功能,或者使用操作系统提供的工具来监控文件系统的变化
sockaddr_un
:这是一个用于表示本地通信(即在同一台机器上的进程间通信)的地址结构。它主要用于Unix域套接字(Unix Domain Sockets)。sockaddr_un
结构体包含一个长度和一个路径名。长度字段表示路径名的长度,路径名则是一个文件系统路径,用于标识特定的Unix域套接字。
sockaddr_in
:这是一个用于表示Internet协议(IPv4)的网络地址的结构。它包含了一个网络字节序的32位整数(用于存储IP地址),一个网络字节序的16位整数(用于存储端口号),以及其他一些字段。
以下是这两个结构的C语言定义:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* Pathname */
};
struct sockaddr_in {
short sin_family; /* e.g. AF_INET */
unsigned short sin_port; /* e.g. htons(3490) */
struct in_addr sin_addr; /* see struct in_addr, below */
char sin_zero[8]; /* zero this if you want to */
};
在创建套接字并进行连接或绑定操作时,可能需要使用这些结构。例如,可以创建一个sockaddr_in
结构并将其传递给bind()
函数,以便将套接字绑定到特定的IP地址和端口号。同样,你也可以创建一个sockaddr_un
结构并将其传递给connect()
或bind()
函数,以便进行本地通信。
#include
#include
#include
#include
#include
int main() {
struct sockaddr_un server_address;
int server_fd;
char buffer[1024];
server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket error");
exit(EXIT_FAILURE);
}
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "/tmp/domain_socket");
if (bind(server_fd, (struct sockaddr*)&server_address, sizeof(struct sockaddr_un)) == -1) {
perror("bind error");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 5) == -1) {
perror("listen error");
exit(EXIT_FAILURE);
}
int client_fd;
struct sockaddr_un client_address;
socklen_t client_len = sizeof(client_address);
client_fd = accept(server_fd, (struct sockaddr*)&client_address, &client_len);
if (client_fd == -1) {
perror("accept error");
exit(EXIT_FAILURE);
}
read(client_fd, buffer, 1024);
printf("Received: %s\n", buffer);
close(client_fd);
close(server_fd);
unlink("/tmp/domain_socket");
return 0;
}
#include
#include
#include
#include
#include
int main() {
struct sockaddr_un server_address;
int client_fd;
client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (client_fd == -1) {
perror("socket error");
exit(EXIT_FAILURE);
}
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "/tmp/domain_socket");
if (connect(client_fd, (struct sockaddr*)&server_address, sizeof(struct sockaddr_un)) == -1) {
perror("connect error");
exit(EXIT_FAILURE);
}
char *message = "Hello from client";
write(client_fd, message, strlen(message));
close(client_fd);
return 0;
}