C语言Socket示例
1. Socket客户端
2. Socket服务器(单进程单连接)
3. Socket服务器(多进程多连接)
4. Socket服务器(多线程多连接)
1. Socket客户端
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #define PORT 8088 #define SIZE 1024 int main() { // int socket(int family, int type, int protocol); int client_socket = socket(AF_INET, SOCK_STREAM, 0); // 创建一个Socket,返回大于0的文件描述符。 if(client_socket == -1){ perror("socket"); return -1; } // 定义sockaddr_in结构体 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; // 标记为IPv4 addr.sin_port = htons(PORT); // 绑定端口 addr.sin_addr.s_addr = inet_addr("172.16.37.130"); // 指定Server IP地址 // int connect(int sock_fd, struct sockaddr *server_addr,int addr_len); int conn = connect(client_socket, (struct sockaddr *)&addr, sizeof(addr)); // 向服务器发送连接请求。 if(conn == -1){ perror("connect"); return -1; } printf("成功连接到一个服务器\n"); char buf[SIZE] = {0}; while (1){ printf("请输入你想输入的:"); scanf("%s", buf); write(client_socket, buf, strlen(buf)); // 向Socket文件描述符写入内容 int ret = read(client_socket, buf, strlen(buf)); // 从Socket文件描述符中读取内容 printf("ret size : %d\n", ret); printf("buf = %s\n", buf); if(strncmp(buf, "END", 3) == 0){ break; } } close(client_socket); // 关闭Socket文件描述符 return 0; }
2. Socket服务器(单进程单连接)
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #define PORT 8088 //端口号 #define SIZE 1024 //定义的数组大小 int create_socket() //创建套接字和初始化以及监听函数 { int listen_socket = socket(AF_INET, SOCK_STREAM, 0); // 创建一个负责监听的Socket文件描述符 if (listen_socket == -1) { perror("socket"); return -1; } // 定义socket_addr结构体 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; // Internet地址族 addr.sin_port = htons(PORT); // 监听端口号 addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定任何地址 // 将Socket文件描述符和sock_addr进行绑定 // int bind(int sock_fd, const struct sockaddr *addr, socklen_t addr_len); int ret = bind(listen_socket, (struct sockaddr *) &addr, sizeof(addr)); if (ret == -1) { perror("bind"); return -1; } // 开始监听客户端连接,并限制最大连接数 ret = listen(listen_socket, 5); if (ret == -1) { perror("listen"); return -1; } return listen_socket; } int wait_client(int listen_socket) // 等待客户端连接处理函数 { struct sockaddr_in client_addr; int addr_len = sizeof(client_addr); printf("等待客户端连接。。。。\n"); // 等待客户端连接,并把客户端的协议族、网络地址、端口号都存入client_addr中,然后返回一个客户端fd。 // int accept(int sock_fd, struct sockaddr *client_addr, socklen_t *len); int client_socket = accept(listen_socket, (struct sockaddr *) &client_addr, &addr_len); if (client_socket == -1) { perror("accept"); return -1; } printf("成功接收到一个客户端:%s\n", inet_ntoa(client_addr.sin_addr)); return client_socket; } void handle_client(int client_socket) // 信息处理函数,功能是将客户端传过来的小写字母转化为大写字母 { char buf[SIZE]; while (1) { int ret = read(client_socket, buf, SIZE - 1); // 从客户端fd中读取内容 if (ret == -1) { perror("read"); break; } if (ret == 0) { break; } buf[ret] = '\0'; int i; for (i = 0; i < ret; i++) { buf[i] = buf[i] + 'A' - 'a'; } printf("%s\n", buf); write(client_socket, buf, ret); // 向客户端fd写入内容 if (strncmp(buf, "end", 3) == 0) { break; } } close(client_socket); // 关闭客户端fd } int main() { int listen_socket = create_socket(); int client_socket = wait_client(listen_socket); handle_client(client_socket); close(listen_socket); return 0; }
3. Socket服务器(多进程多连接)
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #include <sys/wait.h> #define PORT 8088 //端口号 #define SIZE 1024 //定义的数组大小 int create_socket() //创建套接字和初始化以及监听函数 { int listen_socket = socket(AF_INET, SOCK_STREAM, 0); // 创建一个负责监听的Socket文件描述符 if (listen_socket == -1) { perror("socket"); return -1; } // 定义socket_addr结构体 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; // Internet地址族 addr.sin_port = htons(PORT); // 监听端口号 addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定任何地址 // 将Socket文件描述符和sock_addr进行绑定 // int bind(int sock_fd, const struct sockaddr *addr, socklen_t addr_len); int ret = bind(listen_socket, (struct sockaddr *) &addr, sizeof(addr)); if (ret == -1) { perror("bind"); return -1; } // 开始监听客户端连接,并限制最大连接数 ret = listen(listen_socket, 5); if (ret == -1) { perror("listen"); return -1; } return listen_socket; } int wait_client(int listen_socket) // 等待客户端连接处理函数 { struct sockaddr_in client_addr; int addr_len = sizeof(client_addr); printf("等待客户端连接。。。。\n"); // 等待客户端连接,并把客户端的协议族、网络地址、端口号都存入client_addr中,然后返回一个客户端fd。 // int accept(int sock_fd, struct sockaddr *client_addr, socklen_t *len); int client_socket = accept(listen_socket, (struct sockaddr *) &client_addr, &addr_len); if (client_socket == -1) { perror("accept"); return -1; } printf("成功接收到一个客户端:%s\n", inet_ntoa(client_addr.sin_addr)); return client_socket; } void handle_client(int client_socket) // 信息处理函数,功能是将客户端传过来的小写字母转化为大写字母 { char buf[SIZE]; while (1) { int ret = read(client_socket, buf, SIZE - 1); // 从客户端fd中读取内容 if (ret == -1) { perror("read"); break; } if (ret == 0) { break; } buf[ret] = '\0'; int i; for (i = 0; i < ret; i++) { buf[i] = buf[i] + 'A' - 'a'; } printf("%s\n", buf); write(client_socket, buf, ret); // 向客户端fd写入内容 if (strncmp(buf, "end", 3) == 0) { break; } } close(client_socket); // 关闭客户端fd } void handler(int sig) { while (waitpid(-1, NULL, WNOHANG) > 0) { printf("成功处理一个子进程的退出\n"); } } int main() { int listen_socket = create_socket(); signal(SIGCHLD, handler); //处理子进程,防止僵尸进程的产生 while(1){ int client_socket = wait_client(listen_socket); // 开启一个子进程 int pid = fork(); if(pid == -1){ perror("fork"); break; } // pid > 0 表示父进程 if(pid > 0) { close(client_socket); continue; } // pid = 0 表示子进程 if(pid == 0){ close(client_socket); handle_client(client_socket); break; } } close(listen_socket); return 0; }
4. Socket服务器(多线程多连接)