您现在的位置是:首页 > 经典句子

Socket编程详解:从基本概念到实例应用(TCP|UDP C语言实例详解)

作者:纳雷武时间:2024-03-24 15:05:41分类:经典句子

简介  文章浏览阅读1.1w次,点赞15次,收藏243次。Socket编程详解:从基本概念到实例应用_socket编程

点击全文阅读

简介:
Socket编程是网络编程中至关重要的一部分,它提供了一种在不同主机之间进行数据通信的方式。本篇博客将详细介绍Socket编程的基本概念、原理和实例应用,帮助读者深入理解和掌握这一重要技术。

正文:
一、Socket编程概述
Socket是一种通信机制,通过它可以在不同主机之间进行数据交换。在Socket编程中,有两种常见的通信模式:客户端-服务器模式和点对点模式。它基于TCP/IP协议栈,并使用IP地址和端口号来标识通信的目标。

二、Socket编程基本步骤
Socket编程是一种用于实现网络通信的编程接口,可以通过TCP(传输控制协议)和UDP(用户数据报协议)实现不同类型的连接。下面将详细介绍TCP和UDP的开发流程,并详细介绍常用的Socket编程函数的原型和参数用法。

TCP开发流程:

服务器端:

创建套接字:int serverSocket = socket(AF_INET, SOCK_STREAM, 0);绑定地址:struct sockaddr_in serverAddress; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));监听连接:listen(serverSocket, backlog);接受连接:struct sockaddr_in clientAddress; int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, sizeof(clientAddress));发送和接收数据:send(clientSocket, buffer, size, 0); recv(clientSocket, buffer, size, 0);关闭连接:close(clientSocket); close(serverSocket);

客户端:

创建套接字:int clientSocket = socket(AF_INET, SOCK_STREAM, 0);连接服务器:struct sockaddr_in serverAddress; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = inet_addr(serverIP); connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));发送和接收数据:send(clientSocket, buffer, size, 0); recv(clientSocket, buffer, size, 0);关闭连接:close(clientSocket);

UDP开发流程:

服务器端:

创建套接字:int serverSocket = socket(AF_INET, SOCK_DGRAM, 0);绑定地址:struct sockaddr_in serverAddress; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));接收和发送数据:recvfrom(serverSocket, buffer, size, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress)); sendto(serverSocket, buffer, size, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress));关闭套接字:close(serverSocket);

客户端:

创建套接字:int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);发送和接收数据:sendto(clientSocket, buffer, size, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress)); recvfrom(clientSocket, buffer, size, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress));关闭套接字:close(clientSocket);

常用函数的原型和参数用法详解:

socket()函数: 原型:int socket(int domain, int type, int protocol);参数: domain:地址族,通常为AF_INET(IPv4)或AF_INET6(IPv6)。type:套接字类型,可以是SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)。protocol:协议,通常为0,表示自动选择合适的协议。

2

. bind()函数:

原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数: sockfd:套接字描述符。addr:指向本地地址结构体的指针。addrlen:地址结构体的长度。

listen()函数:

原型:int listen(int sockfd, int backlog);参数: sockfd:套接字描述符。backlog:待连接队列的最大长度。

accept()函数:

原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);参数: sockfd:套接字描述符。addr:指向客户端地址结构体的指针,用于存储客户端的地址信息。addrlen:指向地址结构体长度的指针。

connect()函数:

原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数: sockfd:套接字描述符。addr:指向目标地址结构体的指针。addrlen:地址结构体的长度。

send()函数:

原型:ssize_t send(int sockfd, const void *buf, size_t len, int flags);参数: sockfd:套接字描述符。buf:指向要发送数据的缓冲区的指针。len:要发送的数据的长度。flags:发送标志,通常为0。

recv()函数:

原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);参数: sockfd:套接字描述符。buf:指向接收数据的缓冲区的指针。len:要接收的数据的最大长度。flags:接收标志,通常为0。

sendto()函数:

原型:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);参数: sockfd:套接字描述符。buf:指向要发送数据的缓冲区的指针。len:要发送的数据的长度。flags:发送标志,通常为0。dest_addr:指向目标地址结构体的指针。addrlen:目标地址结构体的长度。

recvfrom()函数:

原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);参数: sockfd:套接字描述符。buf:指向接收数据的缓冲区的指针。len:要接收的数据的最大长度。flags:接收标志,通常为0。src_addr:指向源地址结构体的指针,用于存储源地址信息。addrlen:指向地址结构体长度的指针。

close()函数:

原型:int close(int sockfd);
- 参数:套接字描述符。

通过使用这些函数,可以实现TCP和UDP通信的服务器端和客户端程序。TCP提供可靠的、面向连接的通信,适用于需要确保数据可靠性和顺序性的场景,而UDP提供无连接的通信,适用于实时性要求较高但可靠性要求较低的场景。

三、Socket编程实例

以下是使用C语言通过Socket实现TCP和UDP通信的服务端和客户端通信程序的示例:

TCP通信示例:

服务端(server.c):

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"#define SERVER_PORT 8080#define BUFFER_SIZE 1024int main() {    int serverSocket, clientSocket;    struct sockaddr_in serverAddr, clientAddr;    socklen_t clientAddrLen;    char buffer[BUFFER_SIZE];    // 创建服务端套接字    serverSocket = socket(AF_INET, SOCK_STREAM, 0);    if (serverSocket == -1) {        perror("Failed to create socket");        exit(EXIT_FAILURE);    }    // 设置服务器地址信息    memset(&serverAddr, 0, sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);    // 绑定套接字到指定地址和端口    if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {        perror("Failed to bind socket");        exit(EXIT_FAILURE);    }    // 监听连接请求    if (listen(serverSocket, 5) == -1) {        perror("Failed to listen");        exit(EXIT_FAILURE);    }    printf("Server listening on port %d...\n", SERVER_PORT);    // 接受客户端连接    clientAddrLen = sizeof(clientAddr);    clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &clientAddrLen);    if (clientSocket == -1) {        perror("Failed to accept client connection");        exit(EXIT_FAILURE);    }    printf("Client connected: %s\n", inet_ntoa(clientAddr.sin_addr));    // 接收数据    memset(buffer, 0, sizeof(buffer));    if (recv(clientSocket, buffer, BUFFER_SIZE, 0) == -1) {        perror("Failed to receive data");        exit(EXIT_FAILURE);    }    printf("Client message: %s\n", buffer);    // 发送响应    strcpy(buffer, "Hello, Client!");    if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {        perror("Failed to send data");        exit(EXIT_FAILURE);    }    // 关闭套接字    close(clientSocket);    close(serverSocket);    return 0;}

客户端(client.c):

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"#define SERVER_PORT 8080#define BUFFER_SIZE 1024int main() {    int clientSocket;    struct sockaddr_in serverAddr;    char buffer[BUFFER_SIZE];    // 创建客户端套接字    clientSocket = socket(AF_INET, SOCK_STREAM, 0);    if (clientSocket == -1) {        perror("Failed to create socket");        exit(EXIT_FAILURE);    }    // 设置服务器地址信息    memset(&serverAddr, 0, sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);    if (inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr)) <= 0) {        perror("Failed to set server IP");        exit(EXIT_FAILURE);    }    // 连接到服务器    if (connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {        perror("Failed to connect to server");        exit(EXIT_FAILURE);    }    printf("Connected to server %s:%d\n", SERVER_IP, SERVER_PORT);    // 发送数据    strcpy(buffer, "Hello, Server!");    if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {        perror("Failed to send data");        exit(EXIT_FAILURE);    }    // 接收响应    memset(buffer, 0, sizeof(buffer));    if (recv(clientSocket, buffer, BUFFER_SIZE, 0) == -1) {        perror("Failed to receive data");        exit(EXIT_FAILURE);    }    printf("Server response: %s\n", buffer);    // 关闭套接字    close(clientSocket);    return 0;}

UDP通信示例:

服务端(server.c):

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"#define SERVER_PORT 8080#define BUFFER_SIZE 1024int main() {    int serverSocket;    struct sockaddr_in serverAddr, clientAddr;    socklen_t clientAddrLen;    char buffer[BUFFER_SIZE];    // 创建服务端套接字    serverSocket = socket(AF_INET, SOCK_DGRAM, 0);    if (serverSocket == -1) {        perror("Failed to create socket");        exit(EXIT_FAILURE);    }    // 设置服务器地址信息    memset(&serverAddr, 0, sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);    // 绑定套接字到指定地址和端口    if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {        perror("Failed to bind socket");        exit(EXIT_FAILURE);    }    printf("Server listening on port %d...\n", SERVER_PORT);    // 接收数据    clientAddrLen = sizeof(clientAddr);    memset(buffer, 0, sizeof(buffer));    if (recvfrom(serverSocket, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&clientAddr, &clientAddrLen) == -1) {        perror("Failed to receive data");        exit(EXIT_FAILURE);    }    printf("Client message: %s\n", buffer);    // 发送响应    strcpy(buffer, "Hello, Client!");    if (sendto(serverSocket, buffer, strlen(buffer), 0, (struct sockaddr *)&clientAddr, clientAddrLen) == -1) {        perror("Failed to send data");        exit(EXIT_FAILURE);    }    // 关闭套接字    close(serverSocket);    return 0;}

客户端(client.c):

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"#define SERVER_PORT 8080#define BUFFER_SIZE 1024int main() {    int clientSocket;    struct sockaddr_in serverAddr;    char buffer[BUFFER_SIZE];    // 创建客户端套接字    clientSocket = socket(AF_INET, SOCK_DGRAM, 0);    if (clientSocket == -1) {        perror("Failed to create socket");        exit(EXIT_FAILURE);    }    // 设置服务器地址信息    memset(&serverAddr, 0, sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);    if (inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr)) <= 0) {        perror("Failed to set server IP");        exit(EXIT_FAILURE);    }    printf("Connected to server %s:%d\n", SERVER_IP, SERVER_PORT);    // 发送数据    strcpy(buffer, "Hello, Server!");    if (sendto(clientSocket, buffer, strlen(buffer), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {        perror("Failed to send data");        exit(EXIT_FAILURE);    }    // 接收响应    memset(buffer, 0, sizeof(buffer));    if (recvfrom(clientSocket, buffer, BUFFER_SIZE, 0, NULL, NULL) == -1) {        perror("Failed to receive data");        exit(EXIT_FAILURE);    }    printf("Server response: %s\n", buffer);    // 关闭套接字    close(clientSocket);    return 0;}

这些示例代码分别实现了TCP和UDP的服务端和客户端通信。你可以根据需要进行编译并运行这些代码,它们将在本地主机上创建一个套接字连接,通过网络进行通信。TCP是面向连接的可靠传输协议,而UDP是面向无连接的不可靠传输协议,它们在使用上有一些区别。

TCP相对于UDP具有以下特点:

TCP提供可靠的、面向连接的通信,确保数据的准确传输和顺序交付。TCP使用三次握手建立连接,并通过应答机制进行数据的确认和重传,保证数据的可靠性。TCP具有拥塞控制和流量控制的机制,能够根据网络情况动态调整发送速率,防止网络拥塞。TCP适用于对数据准确性要求高、顺序要求严格的应用场景,如文件传输、网页浏览等。

UDP相对于TCP具有以下特点:

UDP是无连接的通信协议,发送方将数据以数据包的形式发送给接收方,没有建立和维护连接的过程。UDP不提供数据的可靠性和顺序交付,发送方将数据包发送给接收方后不会进行确认和重传操作。UDP具有较低的延迟和较小的开销,适用于对实时性要求较高、对数据准确性要求相对较低的应用场景,如实时视频、音频传输等。

通过这些示例代码,你可以了解如何使用C语言通过Socket实现TCP和UDP的通信,并了解到TCP和UDP在使用上的差异和

适用场景。你可以根据需要对代码进行修改和扩展,实现更复杂的功能和应用。

总结:
Socket编程是网络编程中的重要技术,通过Socket可以实现不同主机之间的数据通信。本篇博客介绍了Socket编程的基本概念和原理,以及通过一个简单的聊天应用示例展示了其实际应用。深入理解和掌握Socket编程将有助于嵌入式开发者在网络通信领域取得更好的成果。

引用:Linux的SOCKET编程详解

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

上一篇:小学2年级教师评语

下一篇:返回列表

我来说两句