一、c socket 异步接收
c socket支持两种类型的接收模式:阻塞模式和非阻塞模式,但是在大量的数据传输时,阻塞模式一定会造成数据的丢失和延迟,所以使用异步接收通常是一个更加可靠的解决办法。在c++ socket中,我们可以使用select函数来实现异步接收。
while(1) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(sock_fd, &read_fds); if(select(sock_fd+1, &read_fds, NULL, NULL, NULL) <= 0) { continue; } if(FD_ISSET(sock_fd, &read_fds)) { recv(sock_fd, buffer, size, 0); } }
在上述代码中,我们使用select函数监听我们的socket,当有数据可读时,便会进入recv函数来接收数据。
二、c socket 长连接
在网络编程中,短连接是指每次请求都需要建立一个新的连接,而长连接则是可以一直保持连接状态,在后续请求中都可以复用这个连接。
在c++ socket中,通过设置socket的选项SO_KEEPALIVE为1(开启TCP心跳包机制)和TCP_NODELAY为1(禁用Nagle算法),我们可以实现长连接的功能。
int optval = 1; setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
三、c socket技术
c++ socket编程中需要使用到的技术包括:TCP/IP协议、Socket编程、多线程、select的应用、数据加密和压缩等。以下是一个基本的c++ socket示例代码,实现了TCP连接和发送一条消息的功能。
#include#include #include #include #include #include #include int main(int argc, char *argv[]) { int sock_fd; struct sockaddr_in server_addr; char msg[] = "Hello, world!"; // create socket sock_fd = socket(AF_INET, SOCK_STREAM, 0); if(sock_fd == -1) { perror("socket failed"); exit(EXIT_FAILURE); } // set server address server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // connect to server if(connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("connect failed"); exit(EXIT_FAILURE); } // send message if(send(sock_fd, msg, strlen(msg), 0) < 0) { perror("send failed"); exit(EXIT_FAILURE); } // close socket close(sock_fd); return 0; }
四、c socket通讯源代码
以下是一个基于select函数实现的简单通信源代码,包括服务器端和客户端。
服务器端
#include#include #include #include #include #include #include int main(int argc, char *argv[]) { int listen_fd, max_fd, client_fd[FD_SETSIZE], conn_fd; int nready; struct sockaddr_in server_addr, client_addr; socklen_t client_len; char buffer[256]; fd_set read_set, all_set; int i; // create listen socket listen_fd = socket(AF_INET, SOCK_STREAM, 0); if(listen_fd == -1) { perror("socket failed"); exit(EXIT_FAILURE); } // set server address server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = htons(INADDR_ANY); // bind listen_fd if(bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // listen to client requests if(listen(listen_fd, 10) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } max_fd = listen_fd; for(i = 0; i < FD_SETSIZE; i++) client_fd[i] = -1; FD_ZERO(&all_set); FD_SET(listen_fd, &all_set); printf("Server running...\n"); while(1) { read_set = all_set; nready = select(max_fd+1, &read_set, NULL, NULL, NULL); if(nready < 0) { perror("select failed"); exit(EXIT_FAILURE); } // if new client request if(FD_ISSET(listen_fd, &read_set)) { client_len = sizeof(client_addr); conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len); if(conn_fd < 0) { perror("accept failed"); continue; } for(i = 0; i < FD_SETSIZE; i++) { if(client_fd[i] < 0) { client_fd[i] = conn_fd; break; } } if(i == FD_SETSIZE) { printf("too many clients\n"); close(conn_fd); } printf("New client connected\n"); FD_SET(conn_fd, &all_set); if(conn_fd > max_fd) { max_fd = conn_fd; } } for(i = 0; i < FD_SETSIZE; i++) { if(client_fd[i] < 0) continue; if(FD_ISSET(client_fd[i], &read_set)) { memset(buffer, 0, sizeof(buffer)); if(read(client_fd[i], buffer, sizeof(buffer)-1) == 0) { printf("client[%d] closed\n", i); close(client_fd[i]); FD_CLR(client_fd[i], &all_set); client_fd[i] = -1; } else { printf("recv from client[%d]: %s\n", i, buffer); } } } } // close listen_fd close(listen_fd); return 0; }
客户端
#include#include #include #include #include #include int main(int argc, char *argv[]) { int sock_fd; struct sockaddr_in server_addr; char buffer[256]; // create socket sock_fd = socket(AF_INET, SOCK_STREAM, 0); if(sock_fd == -1) { perror("socket failed"); exit(EXIT_FAILURE); } // set server address server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // connect to server if(connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("connect failed"); exit(EXIT_FAILURE); } // send message strcpy(buffer, "Hello, world!"); send(sock_fd, buffer, strlen(buffer), 0); printf("send message: %s\n", buffer); // close socket close(sock_fd); return 0; }
五、c socket设置阻塞
在c++ socket编程中,我们默认使用阻塞模式来进行通信,即当进行读写操作时,程序将一直等待,直到I/O操作完成或者到达超时时间。
阻塞模式可以通过设置socket的O_NONBLOCK选项来实现非阻塞模式:
int flags = fcntl(sock_fd, F_GETFL, 0); fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);
六、c socket传输
c++ socket中传输数据通常是通过send和recv函数进行。以下是一个基本的发送和接收数据的示例代码:
发送数据
char buffer[256]; strcpy(buffer, "Hello, world!"); send(sock_fd, buffer, strlen(buffer), 0);
接收数据
char buffer[256]; memset(buffer, 0, sizeof(buffer)); recv(sock_fd, buffer, sizeof(buffer)-1, 0); printf("recv message: %s\n", buffer);
七、c socket编程基础
c++ socket编程的基础可以分为以下几个方面:
1. c socket 构造
c++ socket的构造需要使用socket函数,该函数包括三个参数:地址族、套接字类型和协议。
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
2. c socket函数
c++ socket编程需要使用一些关键的函数,包括bind、listen、accept、connect、send和recv等。以下是这些函数的基本使用方法:
bind函数
将socket与地址绑定:
struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); bind(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen函数
告诉socket开始监听连接请求:
listen(sock_fd, 10);
accept函数
接受客户端的连接请求:
struct sockaddr_in client_addr; int client_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &client_len);
connect函数
向服务器发起连接请求:
struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
send函数
发送数据到对端:
char buffer[256]; strcpy(buffer, "Hello, world!"); send(sock_fd, buffer, strlen(buffer), 0);
recv函数
从对端接收数据:
char buffer[256]; memset(buffer, 0, sizeof(buffer)); recv(sock_fd, buffer, sizeof(buffer)-1, 0); printf("recv message: %s\n", buffer);
3. c语言socket通信
在c++ socket编程中,使用的通信协议通常是TCP/IP。
TCP/IP协议采用了面向连接的方式进行通信,可以保证数据的可靠性和完整性。但是,相比于UDP协议,TCP/IP协议的速度会稍微慢一些。
c++ socket编程中应用广泛的通信方式有:单客户端单线程、单客户端多线程、多客户端单线程和多客户端多线程。