宝安附近公司做网站建设哪家效益快,网站开发与设计课程设计,网站建设交接函,网站云主机文章目录 前言代码仓库内容代码#xff08;有详细注释#xff09;server.cclient.cMakefile 结果总结参考资料作者的话 前言
网络编程代码实例#xff1a;多进程版。 代码仓库
yezhening/Environment-and-network-programming-examples: 环境和网络编程实例 (github.com)E… 文章目录 前言代码仓库内容代码有详细注释server.cclient.cMakefile 结果总结参考资料作者的话 前言
网络编程代码实例多进程版。 代码仓库
yezhening/Environment-and-network-programming-examples: 环境和网络编程实例 (github.com)Environment-and-network-programming-examples: 环境和网络编程实例 (gitee.com) 内容
使用传输控制协议TCP一个服务端可连接多个客户端多次手动通信 代码有详细注释
server.c
// 头文件————————————————————
// #include sys/socket.h // socket()、sockaddr、bind()、listen()、accept()、recv()、send()
#include stdio.h //(perror())、printf()
#include stdlib.h //exit()
// #include netinet/in.h //sockaddr_in、htons()
#include string.h //bzero()、strncpy()
#include arpa/inet.h //inet_pton()
// #include unistd.h //close()、fork()
#include errno.h //errno// 全局常量————————————————————
const g_serv_port 6666; // 服务端的端口号
const g_listen_max_count 5; // 监听的最大连接数
const g_buff_size 64; // 消息缓冲区的大小// 函数声明————————————————————
void handle_request(int connect_fd); // 处理请求// 主函数————————————————————
int main(int arg, char *argv[])
{// 网络连接————————————————————int listen_fd; // 监听套接字文件描述符// 创建套接字并获取套接字文件描述符if ((listen_fd socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) -1){perror(socket() error);exit(EXIT_FAILURE);}struct sockaddr_in serv_addr; // 服务端网络信息结构体// 初始化服务端网络信息结构体bzero(serv_addr, sizeof(serv_addr));serv_addr.sin_family AF_INET;serv_addr.sin_port htons(g_serv_port);if ((inet_pton(AF_INET, 0.0.0.0, serv_addr.sin_addr)) ! 1){perror(inet_pton() error);exit(EXIT_FAILURE);}// 绑定套接字与网络信息if ((bind(listen_fd, (struct sockaddr *)(serv_addr), sizeof(serv_addr))) -1){if ((close(listen_fd)) -1){perror(bind() close() error);exit(EXIT_FAILURE);}perror(bind() error);exit(EXIT_FAILURE);}// 套接字设置被动监听状态if ((listen(listen_fd, g_listen_max_count)) -1){if ((close(listen_fd)) -1){perror(listen() close() error);exit(EXIT_FAILURE);}perror(listen() error);exit(EXIT_FAILURE);}struct sockaddr_in clie_addr; // 客户端网络信息结构体int clie_addr_size; // 客户端网络信息结构体大小int connect_fd; // 连接套接字文件描述符bzero(clie_addr, sizeof(clie_addr));clie_addr_size sizeof(struct sockaddr);pid_t pid; // 进程号// 循环监听客户端请求// 原则父进程不能退出子进程可以退出while (1){// 与客户端建立连接if ((connect_fd accept(listen_fd, (struct sockaddr *)(clie_addr), clie_addr_size)) -1){perror(accept() error);continue; // 继续监听}// 创建子进程处理请求pid fork();if (pid -1) // 错误{perror(fork() error);continue; // 继续监听}else if (pid 0) // 子进程{if ((close(listen_fd)) -1) // 1.关闭监听套接字文件描述符{if ((close(connect_fd)) -1){perror(fork() close() connect_fd child_process error);exit(EXIT_FAILURE); // 子进程退出}perror(fork() close() listen_fd child_process error);exit(EXIT_FAILURE); // 子进程退出}handle_request(connect_fd); // 2.处理请求if ((close(connect_fd)) -1) // 3.关闭连接套接字文件描述符{perror(fork() close() connect_fd2 child_process error);exit(EXIT_FAILURE); // 子进程退出}exit(EXIT_SUCCESS);}else if (pid 0) // 父进程{if ((close(connect_fd)) -1) // 关闭连接套接字文件描述符{perror(fork() close() connect_fd parent_process error);continue; // 继续监听}}}if ((close(listen_fd)) -1) // 父进程关闭监听套接字文件描述符。实际不会执行{perror(close() listen_fd error);exit(EXIT_FAILURE);}return 0;
}// 函数定义————————————————————
// 处理请求
void handle_request(int connect_fd) // 参数连接套接字文件描述符
{// 传输消息————————————————————char msg_recv[g_buff_size]; // 从客户端接收的消息缓冲区char msg_send[g_buff_size]; // 发送到客户端的消息缓冲区int recv_bytes; // 接收的消息字节数while (1) // 循环接收和发送消息{bzero(msg_recv, sizeof(*msg_recv));bzero(msg_send, sizeof(*msg_send));recv_bytes recv(connect_fd, msg_recv, g_buff_size, 0); // 接收消息if (recv_bytes 0) // 有消息{printf(Received message: %s, msg_recv); // 接收的消息strncpy(msg_send, msg_recv, g_buff_size); // 发送的消息if ((send(connect_fd, msg_send, g_buff_size, 0)) -1) // 发送消息{perror(send() error);return; // 函数返回后关闭连接套接字文件描述符结束子进程}}else if (recv_bytes 0) // 文件末尾EOF在客户端标准输入CtrlD{printf(The process %d received the end of file\n, getpid());return; // 函数返回后关闭连接套接字文件描述符结束子进程}else if ((recv_bytes -1) (errno EINTR)) // 信号或网络中断recv(){continue; // 继续接收消息}else if (recv_bytes -1) // 错误{perror(recv() error);return; // 函数返回后关闭连接套接字文件描述符结束子进程}}return;
}client.c
// 头文件————————————————————
// #include sys/socket.h //socket()、sockaddr、connect()、send()、recv()
#include stdio.h //perror()、printf()、fgets()
#include stdlib.h //exit()
// #include netinet/in.h //sockaddr_in、htons()
#include string.h //bzero()、strncpy()
#include arpa/inet.h //inet_pton()
// #include unistd.h //close()
#include errno.h //errno// 全局常量————————————————————
const g_serv_port 6666; // 服务端端口号
const g_buff_size 64; // 消息缓冲区大小// 函数声明————————————————————
void handle(int sock_fd); // 处理// 主函数————————————————————
int main(int argc, char *argv[])
{// 网络连接————————————————————int sock_fd; // 套接字文件描述符// 创建套接字并获取套接字文件描述符if ((sock_fd socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) -1){perror(socket() error);exit(EXIT_FAILURE);}struct sockaddr_in serv_addr; // 服务端网络信息结构体// 初始化服务端网络信息结构体bzero(serv_addr, sizeof(serv_addr));serv_addr.sin_family AF_INET;serv_addr.sin_port htons(g_serv_port);if ((inet_pton(AF_INET, 127.0.0.1, serv_addr.sin_addr)) ! 1){perror(inet_pton() error);exit(EXIT_FAILURE);}// 与服务端建立连接if ((connect(sock_fd, (struct sockaddr *)(serv_addr), sizeof(serv_addr))) -1){if ((close(sock_fd)) -1){perror(connect() close() error);exit(EXIT_FAILURE);}perror(connect() error);exit(EXIT_FAILURE);}handle(sock_fd); // 处理// 关闭套接字文件描述符if ((close(sock_fd)) -1){perror(close() error);exit(EXIT_FAILURE);}return 0;
}// 函数定义————————————————————
// 处理
void handle(int sock_fd) // 参数套接字文件描述符
{// 传输消息————————————————————char msg_send[g_buff_size]; // 发送到服务端的消息缓冲区char msg_recv[g_buff_size]; // 从服务端接收的消息缓冲区int recv_bytes; // 接收的消息字节数while (1) // 循环发送和接收消息{bzero(msg_send, sizeof(*msg_send));bzero(msg_recv, sizeof(*msg_recv));printf(Send message: );if ((fgets(msg_send, g_buff_size, stdin)) NULL)// 从标准输入获取消息。错误或遇到文件结尾(EOF)在客户端标准输入CtrlD相当于关闭连接{printf(End of connection\n);return; // 函数返回后关闭套接字文件描述符结束进程}if ((send(sock_fd, msg_send, g_buff_size, 0)) -1) // 发送消息{perror(send() error);return; // 函数返回后关闭连接套接字文件描述符结束进程}recv_bytes recv(sock_fd, msg_recv, g_buff_size, 0); // 接收消息if (recv_bytes 0) // 有数据{printf(Received message: %s, msg_recv); // 接收的消息}else if (recv_bytes 0) // 服务端进程提前终止在服务端标准输入CtrlC中断进程{printf(Server terminated prematurely\n);return; // 函数返回后关闭套接字文件描述符结束进程}else if ((recv_bytes -1) (errno EINTR)) // 信号或网络中断recv(){continue; // 继续发送和接收数据}else if (recv_bytes -1) // 错误{perror(recv() error);return; // 函数返回后关闭套接字文件描述符结束进程}}return;
}Makefile
#变量
targets server client#伪目标
.PHONY : all
all : $(targets) #规则
server : server.cgcc -o server server.c client : client.cgcc -o client client.c#伪目标
.PHONY : clean
clean :rm $(targets)结果
正常情况服务端表现 正常情况客户端1表现 正常情况客户端2表现 正常情况客户端3表现 服务端终止服务端表现 服务端终止客户端表现 客户端终止连接服务端表现 客户端终止连接客户端表现 总结
网络编程代码实例多进程版。 参考资料
《UNIX环境高级编程第3版》作者W.Richard StevensStephen A.Rago《UNIX网络编程第3版》作者W.Richard StevensBill FennerAndrew M.Rudoff 作者的话
感谢参考资料的作者/博主作者夜悊版权所有转载请注明出处谢谢~如果文章对你有帮助请点个赞或加个粉丝吧你的支持就是作者的动力~文章在描述时有疑惑的地方请留言定会一一耐心讨论、解答文章在认识上有错误的地方, 敬请批评指正望读者们都能有所收获