您的位置:

c++ socket网络编程详解

一、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编程中应用广泛的通信方式有:单客户端单线程、单客户端多线程、多客户端单线程和多客户端多线程。