Socket编程是网络编程的基础,它允许两个程序在不同的主机上进行通信。无论是构建简单的客户端-服务器应用,还是复杂的分布式系统,Socket编程都是不可或缺的技能。本文将带你从Socket编程的基础概念开始,逐步深入,最终通过实战案例分析,帮助你轻松掌握Socket编程。
Socket编程基础
什么是Socket?
Socket是一种特殊的接口,它允许两个程序通过网络进行通信。在TCP/IP网络中,Socket被广泛使用。
Socket的组成
- IP地址:确定通信双方的网络位置。
- 端口号:确定通信双方的应用程序。
Socket类型
- TCP Socket:提供可靠的、面向连接的服务。
- UDP Socket:提供不可靠的、无连接的服务。
Socket编程步骤
创建Socket
int socket(int domain, int type, int protocol);
连接Socket
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
发送数据
int send(int sockfd, const void *buf, size_t len, int flags);
接收数据
int recv(int sockfd, void *buf, size_t len, int flags);
关闭Socket
int close(int sockfd);
实战案例分析
客户端-服务器模型
服务器端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int server_fd, client_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len = sizeof(client_addr);
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8080);
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
listen(server_fd, 10);
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_fd == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
char buffer[1024];
int n = read(client_fd, buffer, sizeof(buffer));
if (n > 0) {
printf("Received: %s\n", buffer);
}
close(client_fd);
close(server_fd);
return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int client_fd;
struct sockaddr_in server_addr;
char buffer[1024];
client_fd = socket(AF_INET, SOCK_STREAM, 0);
if (client_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(8080);
if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
strcpy(buffer, "Hello, Server!");
write(client_fd, buffer, strlen(buffer));
close(client_fd);
return 0;
}
多线程Socket编程
服务器端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
void *handle_client(void *arg) {
int client_fd = *(int *)arg;
char buffer[1024];
int n = read(client_fd, buffer, sizeof(buffer));
if (n > 0) {
printf("Received: %s\n", buffer);
}
close(client_fd);
free(arg);
return NULL;
}
int main() {
int server_fd, client_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len = sizeof(client_addr);
pthread_t thread_id;
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8080);
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
listen(server_fd, 10);
while (1) {
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_fd == -1) {
perror("accept");
continue;
}
int *client_fd_ptr = malloc(sizeof(int));
*client_fd_ptr = client_fd;
pthread_create(&thread_id, NULL, handle_client, client_fd_ptr);
}
close(server_fd);
return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int client_fd;
struct sockaddr_in server_addr;
char buffer[1024];
client_fd = socket(AF_INET, SOCK_STREAM, 0);
if (client_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(8080);
if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
strcpy(buffer, "Hello, Server!");
write(client_fd, buffer, strlen(buffer));
close(client_fd);
return 0;
}
通过以上实战案例分析,相信你已经对Socket编程有了更深入的了解。只要多加练习,你一定能轻松掌握Socket编程!
