CS架构---Socket基础


一、Socket简介

Socket(套接字)是在网络编程中用于实现网络通信的一种机制。它是一个抽象的概念,可以看作是网络通信的端点,通过套接字可以进行数据的发送和接收。

1.1 通信模型

Socket提供了一种通信模型,使得不同主机之间可以进行数据交换和通信。它允许在不同主机之间建立连接,进行数据的传输和通信。

1.2 类型

在网络编程中,常用的Socket类型有两种:流式套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM)。
流式套接字提供了面向连接的、可靠的、双向的数据传输,使用TCP协议。
数据报套接字提供了无连接的、不可靠的数据传输,使用UDP协议。

1.3 创建和使用:

在使用Socket进行网络编程时,通常需要调用系统提供的Socket API函数,如socket()、bind()、listen()、accept()、connect()、send()、recv()等来创建套接字、绑定地址、监听连接、接受连接、连接远程主机、发送数据、接收数据等操作。

1.4 地址族

在Socket编程中,常用的地址族包括IPv4(AF_INET)、IPv6(AF_INET6)等,用于指定套接字的地址类型。
套接字描述符:

每个Socket都有一个唯一的套接字描述符(Socket Descriptor),用于标识和操作该套接字。套接字描述符是一个整数值,可以用来识别和管理套接字。


二、客户/服务器模式

在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户/服务器(Client/Server, C/S)模式,即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。
客户/服务器模式的建立基于以下两点:

(1)首先,建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用。
(2)其次,网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务器模式的TCP/IP。

在这里插入图片描述

2.1 服务器端(Server Side)

在Socket编程中,服务器端负责监听客户端的连接请求,并处理客户端发送过来的数据。服务器端通常创建一个Socket并绑定到特定的端口,然后通过listen()函数开始监听客户端的连接请求。一旦有客户端连接进来,服务器端会调用accept()函数接受连接,并创建一个新的Socket与客户端进行通信。服务器端可以根据客户端发送的数据进行相应的处理,并向客户端发送数据作为响应。

2.2 客户端(Client Side)

在Socket编程中,客户端负责与服务器端建立连接,并向服务器端发送请求。客户端通常创建一个Socket并通过connect()函数连接到服务器端指定的IP地址和端口。一旦连接建立成功,客户端可以通过该Socket向服务器端发送数据请求,并等待服务器端的响应。客户端接收到服务器端的响应后,可以进行相应的处理和显示。

2.3 通信方式

在Socket编程中,客户端和服务器端之间通过Socket建立连接进行通信。客户端可以向服务器端发送数据请求,服务器端接收请求并进行处理,然后向客户端发送响应。这种请求-响应的通信方式是Socket编程中CS架构的基本通信模式。

2.4 角色分工

在Socket编程中,客户端和服务器端各自承担不同的角色和任务。服务器端负责监听连接请求、处理数据和发送响应;客户端负责建立连接、发送请求和接收响应。通过这种角色分工,实现了Socket编程中CS架构的通信和协作。

2.5 优点

在Socket编程中使用CS架构,可以方便地实现客户端和服务器端之间的通信和数据交换。CS架构具有良好的可扩展性和灵活性,适用于各种网络应用场景。

三、Socket实战

实现一个客户端发送端互发消息的小demo
客户端

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
 
#define BUFSIZE 1024
 
char buffer_send[BUFSIZE] = {0};
char buffer_recv[BUFSIZE] = {0};
 
// send to server
void * sendMsg(void *socket){
	int * client_socket = (int *)socket;
	while(1){
		// send data to server
		scanf("%s", buffer_send);
		printf("client send message: %s",buffer_send);
		send(*client_socket, buffer_send, strlen(buffer_send), 0);
 
		// is exit
		if(!strncasecmp(buffer_send, "quit", 4)){
			break;
		}
	}
	pthread_exit(NULL);
}
 
// recv from server
void * recvMsg(void *socket){
	int * client_socket = (int *)socket;
	while(1){
		// clear buffer_recv
		bzero(buffer_recv, BUFSIZE);
		
		// read data from client
		if(recv(*client_socket, buffer_recv, BUFSIZE, 0) > 0){
			printf("Message from server:%s\n", buffer_recv);
		}
		// is exit
		if(!strncasecmp(buffer_send, "quit", 4)){
			break;
		}
	}
	pthread_exit(NULL);
}
 
int main(){
	// create socket
	int client_socket = socket(AF_INET, SOCK_STREAM, 0);
	
	// requset server
	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(server_addr));// fill zero
	server_addr.sin_family = AF_INET;// use IPV4 address
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");// ip
	server_addr.sin_port = htons(6666);// port
	connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
	
	// clear buffer_recv
	bzero(buffer_recv, BUFSIZE);			
	
	// recv data from server
	if(recv(client_socket, buffer_recv, BUFSIZE, 0) > 0){
		printf("Message from server:%s\n", buffer_recv);
	}
 
	// create send and recv thread
	pthread_t send_thread, recv_thread;
	
	pthread_create(&send_thread, NULL, sendMsg, (void *)&client_socket);
	pthread_create(&recv_thread, NULL, recvMsg, (void *)&client_socket);
 
	// wait send and recv thread over
	pthread_join(send_thread, NULL);
	pthread_join(recv_thread, NULL);
	
	// close
	close(client_socket);
	
	return 0;
}

编译一下:
g++ client.c -o client -pthread

服务端

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
 
#define BUFSIZE 1024
 
char buffer_send[BUFSIZE] = "connect stablish!";
char buffer_recv[BUFSIZE] = {0};
 
// send to client
void * sendMsg(void *socket){
	int * client_socket = (int *)socket;
	while(1){
		// send data to client
		scanf("%s", buffer_send);
		printf("sever send message: %s\n",buffer_send);
		send(*client_socket, buffer_send, strlen(buffer_send), 0);
 
		// is exit
		if(!strncasecmp(buffer_send, "quit", 4)){
			break;
		}
	}
	pthread_exit(NULL);
}
 
// recv from client
void * recvMsg(void *socket){
	int * client_socket = (int *)socket;
	while(1){
		// clear buffer_recv
		bzero(buffer_recv, BUFSIZE);
		
		// read data from client
		if(recv(*client_socket, buffer_recv, BUFSIZE, 0) > 0){
			printf("Message from client:%s\n", buffer_recv);
		}
 
		// is exit
		if(!strncasecmp(buffer_send, "quit", 4)){
			break;
		}
	}
	pthread_exit(NULL);
}
 
int main(){
	// create socket
	int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	
	// bind ip port to socket
	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(server_addr));// use zero fill
	server_addr.sin_family = AF_INET;// use IPV4 address
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");// ip
	server_addr.sin_port = htons(6666); // port
	bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
 
	// listen
	listen(server_socket, 20);
	
	// accept client request
	struct sockaddr_in client_addr;
	socklen_t client_addr_size = sizeof(client_addr);
	int client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
 
	// send stablish info to client
	send(client_socket, buffer_send, strlen(buffer_send), 0);
	
	// create send and recv thread
	pthread_t send_thread, recv_thread;
	
	pthread_create(&send_thread, NULL, sendMsg,(void *)&client_socket);
	pthread_create(&recv_thread, NULL, recvMsg,(void *)&client_socket);
	
	// wait send and recv thread over
	pthread_join(send_thread, NULL);
	pthread_join(recv_thread, NULL);
	
	// close
	close(client_socket);
	close(server_socket);
 
	return 0;
}

编译一下:
g++ sever.c -o sever -pthread

实现的效果:

在这里插入图片描述

四、常见应用场景

  • 网络通信:用于实现客户端和服务器之间的通信,例如Web服务器和浏览器之间的通信。
  • 实时通信:用于实现实时通信应用,如即时通讯软件、在线游戏等。
  • 远程控制:用于实现远程控制应用,如远程桌面、远程监控等。
  • 文件传输:用于实现文件传输功能,如FTP(文件传输协议)。
  • 数据采集:用于实现数据采集和传输,如传感器数据采集系统。
  • 分布式计算:用于实现分布式系统中不同节点之间的通信和协作。
  • 云计算:用于实现云计算平台中不同服务之间的通信和数据交换。
  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中的Socket编程是一种用于创建网络应用程序的常见方法,它基于传输控制协议(TCP)或用户数据报协议(UDP)来实现不同的通信需求。CS架构(Client-Server架构)是一种常见的网络应用程序设计模式,其中服务器端提供服务,而客户端通过Socket连接请求服务。 在C++中进行Socket编程,可以使用操作系统提供的原生Socket API或者一些封装库,如Boost.Asio、Poco、ACE等。下面是一个简单的CS架构的Socket编程示例: 服务器端代码: ```cpp #include <iostream> #include <cstring> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> int main() { // 创建Socket int serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == -1) { std::cerr << "Failed to create socket" << std::endl; return 1; } // 绑定IP地址和端口 sockaddr_in serverAddress{}; serverAddress.sin_family = AF_INET; serverAddress.sin_addr.s_addr = INADDR_ANY; serverAddress.sin_port = htons(12345); if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) { std::cerr << "Failed to bind address" << std::endl; close(serverSocket); return 1; } // 监听连接请求 if (listen(serverSocket, 5) == -1) { std::cerr << "Failed to listen" << std::endl; close(serverSocket); return 1; } // 接受客户端连接 sockaddr_in clientAddress{}; socklen_t clientAddressLength = sizeof(clientAddress); int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength); if (clientSocket == -1) { std::cerr << "Failed to accept client connection" << std::endl; close(serverSocket); return 1; } // 接收和发送数据 char buffer[1024]; std::memset(buffer, 0, sizeof(buffer)); if (recv(clientSocket, buffer, sizeof(buffer), 0) == -1) { std::cerr << "Failed to receive data" << std::endl; close(clientSocket); close(serverSocket); return 1; } std::cout << "Received message from client: " << buffer << std::endl; const char* response = "Hello from server!"; if (send(clientSocket, response, std::strlen(response), 0) == -1) { std::cerr << "Failed to send data" << std::endl; close(clientSocket); close(serverSocket); return 1; } // 关闭连接 close(clientSocket); close(serverSocket); return 0; } ``` 客户端代码: ```cpp #include <iostream> #include <cstring> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { // 创建Socket int clientSocket = socket(AF_INET, SOCK_STREAM, 0); if (clientSocket == -1) { std::cerr << "Failed to create socket" << std::endl; return 1; } // 连接服务器 sockaddr_in serverAddress{}; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(12345); if (inet_pton(AF_INET, "127.0.0.1", &(serverAddress.sin_addr)) <= 0) { std::cerr << "Invalid address" << std::endl; close(clientSocket); return 1; } if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) { std::cerr << "Failed to connect to server" << std::endl; close(clientSocket); return 1; } // 发送和接收数据 const char* message = "Hello from client!"; if (send(clientSocket, message, std::strlen(message), 0) == -1) { std::cerr << "Failed to send data" << std::endl; close(clientSocket); return 1; } char buffer[1024]; std::memset(buffer, 0, sizeof(buffer)); if (recv(clientSocket, buffer, sizeof(buffer), 0) == -1) { std::cerr << "Failed to receive data" << std::endl; close(clientSocket); return 1; } std::cout << "Received message from server: " << buffer << std::endl; // 关闭连接 close(clientSocket); return 0; } ``` 上述代码展示了一个简单的CS架构的Socket编程示例,其中服务器端监听连接请求并与客户端进行通信,客户端通过Socket连接服务器并发送消息,服务器接收消息并回复。你可以根据实际需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值