引言:什么是Sock编程?
Sock编程,即套接字编程,是网络编程的基础。它允许程序员在网络上建立连接、发送和接收数据。无论是开发网页、游戏,还是企业级应用,Sock编程都是不可或缺的技能。本文将带你从基础配置开始,一步步深入学习Sock编程,并通过实战案例让你熟练掌握网络编程技巧。
一、Sock编程基础
1.1 套接字的概念
套接字(Socket)是网络通信的基本单元,它提供了应用程序之间的接口。每个套接字都由四元组(IP地址、端口号、协议类型、套接字类型)唯一标识。
1.2 套接字类型
- 流式套接字(Stream Sockets):提供双向、有序、无结构的字节流,如TCP协议。
- 数据报套接字(Datagram Sockets):提供无连接、不可靠、数据报文的服务,如UDP协议。
1.3 套接字协议
- TCP/IP:传输控制协议/互联网协议,保证数据可靠传输。
- UDP/IP:用户数据报协议/互联网协议,提供不可靠、无连接的服务。
二、Sock编程基础配置
2.1 创建套接字
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
2.2 绑定地址
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
2.3 监听连接
#include <sys/socket.h>
int listen(int sockfd, int backlog);
2.4 接受连接
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
2.5 发送数据
#include <sys/socket.h>
int send(int sockfd, const void *buf, size_t len, int flags);
2.6 接收数据
#include <sys/socket.h>
int recv(int sockfd, void *buf, size_t len, int flags);
2.7 关闭套接字
#include <unistd.h>
int close(int fd);
三、实战案例
3.1 客户端-服务器模型
以下是一个简单的客户端-服务器模型示例:
服务器端代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
perror("accept");
exit(EXIT_FAILURE);
}
read(new_socket, buffer, 1024);
printf("Client message: %s\n", buffer);
send(new_socket, hello, strlen(hello), 0);
close(new_socket);
close(server_fd);
return 0;
}
客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
char *hello = "Hello from client";
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
return -1;
}
send(sock, hello, strlen(hello), 0);
read(sock, buffer, 1024);
printf("Server messsage: %s\n", buffer);
return 0;
}
3.2 多线程服务器
以下是一个多线程服务器示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
void *client_handler(void *socket_desc) {
// ... (省略代码)
}
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
pthread_t thread_id;
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
while ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))) {
if (pthread_create(&thread_id, NULL, client_handler, (void*)&new_socket) != 0) {
perror("could not create thread");
}
pthread_detach(thread_id);
}
if (new_socket < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
return 0;
}
四、总结
通过本文的学习,你应该已经掌握了Sock编程的基础知识和实战技巧。在实际应用中,Sock编程还有很多高级特性等待你去探索。希望本文能帮助你更好地理解和应用Sock编程,让你的网络编程之路更加顺畅。
