簡介:
Socket編程是網(wǎng)絡(luò)編程中至關(guān)重要的一部分,它提供了一種在不同主機之間進行數(shù)據(jù)通信的方式。本篇博客將詳細介紹Socket編程的基本概念、原理和實例應(yīng)用,幫助讀者深入理解和掌握這一重要技術(shù)。
正文:
一、Socket編程概述
Socket是一種通信機制,通過它可以在不同主機之間進行數(shù)據(jù)交換。在Socket編程中,有兩種常見的通信模式:客戶端-服務(wù)器模式和點對點模式。它基于TCP/IP協(xié)議棧,并使用IP地址和端口號來標(biāo)識通信的目標(biāo)。
二、Socket編程基本步驟
Socket編程是一種用于實現(xiàn)網(wǎng)絡(luò)通信的編程接口,可以通過TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報協(xié)議)實現(xiàn)不同類型的連接。下面將詳細介紹TCP和UDP的開發(fā)流程,并詳細介紹常用的Socket編程函數(shù)的原型和參數(shù)用法。
TCP開發(fā)流程:
-
服務(wù)器端:
- 創(chuàng)建套接字: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));
- 監(jiān)聽連接:listen(serverSocket, backlog);
- 接受連接:struct sockaddr_in clientAddress; int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
- 發(fā)送和接收數(shù)據(jù):send(clientSocket, buffer, size, 0); recv(clientSocket, buffer, size, 0);
- 關(guān)閉連接:close(clientSocket); close(serverSocket);
-
客戶端:
- 創(chuàng)建套接字:int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
- 連接服務(wù)器: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));
- 發(fā)送和接收數(shù)據(jù):send(clientSocket, buffer, size, 0); recv(clientSocket, buffer, size, 0);
- 關(guān)閉連接:close(clientSocket);
UDP開發(fā)流程:
-
服務(wù)器端:
- 創(chuàng)建套接字: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));
- 接收和發(fā)送數(shù)據(jù):recvfrom(serverSocket, buffer, size, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress)); sendto(serverSocket, buffer, size, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
- 關(guān)閉套接字:close(serverSocket);
-
客戶端:
- 創(chuàng)建套接字:int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
- 發(fā)送和接收數(shù)據(jù):sendto(clientSocket, buffer, size, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress)); recvfrom(clientSocket, buffer, size, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
- 關(guān)閉套接字:close(clientSocket);
常用函數(shù)的原型和參數(shù)用法詳解:
- socket()函數(shù):
- 原型:int socket(int domain, int type, int protocol);
- 參數(shù):
- domain:地址族,通常為AF_INET(IPv4)或AF_INET6(IPv6)。
- type:套接字類型,可以是SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)。
- protocol:協(xié)議,通常為0,表示自動選擇合適的協(xié)議。
2
. bind()函數(shù):
- 原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 參數(shù):
- sockfd:套接字描述符。
- addr:指向本地地址結(jié)構(gòu)體的指針。
- addrlen:地址結(jié)構(gòu)體的長度。
-
listen()函數(shù):
- 原型:int listen(int sockfd, int backlog);
- 參數(shù):
- sockfd:套接字描述符。
- backlog:待連接隊列的最大長度。
-
accept()函數(shù):
- 原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 參數(shù):
- sockfd:套接字描述符。
- addr:指向客戶端地址結(jié)構(gòu)體的指針,用于存儲客戶端的地址信息。
- addrlen:指向地址結(jié)構(gòu)體長度的指針。
-
connect()函數(shù):
- 原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 參數(shù):
- sockfd:套接字描述符。
- addr:指向目標(biāo)地址結(jié)構(gòu)體的指針。
- addrlen:地址結(jié)構(gòu)體的長度。
-
send()函數(shù):
- 原型:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
- 參數(shù):
- sockfd:套接字描述符。
- buf:指向要發(fā)送數(shù)據(jù)的緩沖區(qū)的指針。
- len:要發(fā)送的數(shù)據(jù)的長度。
- flags:發(fā)送標(biāo)志,通常為0。
-
recv()函數(shù):
- 原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 參數(shù):
- sockfd:套接字描述符。
- buf:指向接收數(shù)據(jù)的緩沖區(qū)的指針。
- len:要接收的數(shù)據(jù)的最大長度。
- flags:接收標(biāo)志,通常為0。
-
sendto()函數(shù):
- 原型:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
- 參數(shù):
- sockfd:套接字描述符。
- buf:指向要發(fā)送數(shù)據(jù)的緩沖區(qū)的指針。
- len:要發(fā)送的數(shù)據(jù)的長度。
- flags:發(fā)送標(biāo)志,通常為0。
- dest_addr:指向目標(biāo)地址結(jié)構(gòu)體的指針。
- addrlen:目標(biāo)地址結(jié)構(gòu)體的長度。
-
recvfrom()函數(shù):
- 原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
- 參數(shù):
- sockfd:套接字描述符。
- buf:指向接收數(shù)據(jù)的緩沖區(qū)的指針。
- len:要接收的數(shù)據(jù)的最大長度。
- flags:接收標(biāo)志,通常為0。
- src_addr:指向源地址結(jié)構(gòu)體的指針,用于存儲源地址信息。
- addrlen:指向地址結(jié)構(gòu)體長度的指針。
-
close()函數(shù):
原型:int close(int sockfd);
- 參數(shù):套接字描述符。
通過使用這些函數(shù),可以實現(xiàn)TCP和UDP通信的服務(wù)器端和客戶端程序。TCP提供可靠的、面向連接的通信,適用于需要確保數(shù)據(jù)可靠性和順序性的場景,而UDP提供無連接的通信,適用于實時性要求較高但可靠性要求較低的場景。
三、Socket編程實例
以下是使用C語言通過Socket實現(xiàn)TCP和UDP通信的服務(wù)端和客戶端通信程序的示例:
TCP通信示例:
服務(wù)端(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 1024
int main() {
int serverSocket, clientSocket;
struct sockaddr_in serverAddr, clientAddr;
socklen_t clientAddrLen;
char buffer[BUFFER_SIZE];
// 創(chuàng)建服務(wù)端套接字
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 設(shè)置服務(wù)器地址信息
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);
}
// 監(jiān)聽連接請求
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));
// 接收數(shù)據(jù)
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);
// 發(fā)送響應(yīng)
strcpy(buffer, "Hello, Client!");
if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {
perror("Failed to send data");
exit(EXIT_FAILURE);
}
// 關(guān)閉套接字
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 1024
int main() {
int clientSocket;
struct sockaddr_in serverAddr;
char buffer[BUFFER_SIZE];
// 創(chuàng)建客戶端套接字
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 設(shè)置服務(wù)器地址信息
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);
}
// 連接到服務(wù)器
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);
// 發(fā)送數(shù)據(jù)
strcpy(buffer, "Hello, Server!");
if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {
perror("Failed to send data");
exit(EXIT_FAILURE);
}
// 接收響應(yīng)
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);
// 關(guān)閉套接字
close(clientSocket);
return 0;
}
UDP通信示例:
服務(wù)端(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 1024
int main() {
int serverSocket;
struct sockaddr_in serverAddr, clientAddr;
socklen_t clientAddrLen;
char buffer[BUFFER_SIZE];
// 創(chuàng)建服務(wù)端套接字
serverSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (serverSocket == -1) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 設(shè)置服務(wù)器地址信息
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);
// 接收數(shù)據(jù)
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);
// 發(fā)送響應(yīng)
strcpy(buffer, "Hello, Client!");
if (sendto(serverSocket, buffer, strlen(buffer), 0, (struct sockaddr *)&clientAddr, clientAddrLen) == -1) {
perror("Failed to send data");
exit(EXIT_FAILURE);
}
// 關(guān)閉套接字
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 1024
int main() {
int clientSocket;
struct sockaddr_in serverAddr;
char buffer[BUFFER_SIZE];
// 創(chuàng)建客戶端套接字
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (clientSocket == -1) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 設(shè)置服務(wù)器地址信息
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);
// 發(fā)送數(shù)據(jù)
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);
}
// 接收響應(yīng)
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);
// 關(guān)閉套接字
close(clientSocket);
return 0;
}
這些示例代碼分別實現(xiàn)了TCP和UDP的服務(wù)端和客戶端通信。你可以根據(jù)需要進行編譯并運行這些代碼,它們將在本地主機上創(chuàng)建一個套接字連接,通過網(wǎng)絡(luò)進行通信。TCP是面向連接的可靠傳輸協(xié)議,而UDP是面向無連接的不可靠傳輸協(xié)議,它們在使用上有一些區(qū)別。
TCP相對于UDP具有以下特點:
- TCP提供可靠的、面向連接的通信,確保數(shù)據(jù)的準(zhǔn)確傳輸和順序交付。
- TCP使用三次握手建立連接,并通過應(yīng)答機制進行數(shù)據(jù)的確認(rèn)和重傳,保證數(shù)據(jù)的可靠性。
- TCP具有擁塞控制和流量控制的機制,能夠根據(jù)網(wǎng)絡(luò)情況動態(tài)調(diào)整發(fā)送速率,防止網(wǎng)絡(luò)擁塞。
- TCP適用于對數(shù)據(jù)準(zhǔn)確性要求高、順序要求嚴(yán)格的應(yīng)用場景,如文件傳輸、網(wǎng)頁瀏覽等。
UDP相對于TCP具有以下特點:
- UDP是無連接的通信協(xié)議,發(fā)送方將數(shù)據(jù)以數(shù)據(jù)包的形式發(fā)送給接收方,沒有建立和維護連接的過程。
- UDP不提供數(shù)據(jù)的可靠性和順序交付,發(fā)送方將數(shù)據(jù)包發(fā)送給接收方后不會進行確認(rèn)和重傳操作。
- UDP具有較低的延遲和較小的開銷,適用于對實時性要求較高、對數(shù)據(jù)準(zhǔn)確性要求相對較低的應(yīng)用場景,如實時視頻、音頻傳輸?shù)取?/li>
通過這些示例代碼,你可以了解如何使用C語言通過Socket實現(xiàn)TCP和UDP的通信,并了解到TCP和UDP在使用上的差異和
適用場景。你可以根據(jù)需要對代碼進行修改和擴展,實現(xiàn)更復(fù)雜的功能和應(yīng)用。
總結(jié):
Socket編程是網(wǎng)絡(luò)編程中的重要技術(shù),通過Socket可以實現(xiàn)不同主機之間的數(shù)據(jù)通信。本篇博客介紹了Socket編程的基本概念和原理,以及通過一個簡單的聊天應(yīng)用示例展示了其實際應(yīng)用。深入理解和掌握Socket編程將有助于嵌入式開發(fā)者在網(wǎng)絡(luò)通信領(lǐng)域取得更好的成果。文章來源:http://www.zghlxwxcb.cn/news/detail-620283.html
引用:Linux的SOCKET編程詳解文章來源地址http://www.zghlxwxcb.cn/news/detail-620283.html
到了這里,關(guān)于Socket編程詳解:從基本概念到實例應(yīng)用(TCP|UDP C語言實例詳解)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!