聊天程序实现
- 用多进程方式实现点对点聊天
- 一个进程用来获得输入,一个进程用来获得对方发来的消息
客户端
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <sys/socket.h> |
| #include <arpa/inet.h> |
| #include <netinet/in.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <signal.h> |
| |
| void handler(int sig) |
| { |
| exit(EXIT_SUCCESS); |
| } |
| |
| int main() |
| { |
| int sock; |
| |
| if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ |
| perror("Creat socket failed."); |
| exit(1); |
| } |
| |
| struct sockaddr_in servaddr; |
| memset(&servaddr, 0, sizeof(servaddr)); |
| servaddr.sin_family = AF_INET; |
| servaddr.sin_port = htons(9000); |
| servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
| |
| |
| if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ |
| perror("connect() error"); |
| exit(1); |
| } |
| |
| |
| |
| pid_t pid; |
| pid = fork(); |
| if(pid == -1){ |
| perror("fork() error"); |
| } |
| if(pid == 0){ |
| |
| char recvbuf[1024] = {0}; |
| while(1){ |
| memset(recvbuf, 0, sizeof(recvbuf)); |
| int ret = read(sock, recvbuf, sizeof(recvbuf)); |
| if(ret == -1){ |
| perror("read() error"); |
| exit(1); |
| } else if(ret == 0){ |
| printf("peer close\n"); |
| break; |
| } |
| fputs(recvbuf, stdout); |
| } |
| close(sock); |
| kill(getppid(), SIGUSR1); |
| exit(EXIT_SUCCESS); |
| } else { |
| |
| |
| signal(SIGUSR1, handler); |
| char sendbuf[1024] = {0}; |
| while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){ |
| write(sock, sendbuf, strlen(sendbuf)); |
| memset(sendbuf, 0, sizeof(sendbuf)); |
| } |
| close(sock); |
| exit(EXIT_SUCCESS); |
| } |
| |
| return 0; |
| } |
服务器端
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <sys/socket.h> |
| #include <arpa/inet.h> |
| #include <netinet/in.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <signal.h> |
| |
| void handler(int sig) |
| { |
| exit(EXIT_SUCCESS); |
| } |
| |
| int main() |
| { |
| int listenfd; |
| |
| if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ |
| perror("Create socket failed."); |
| exit(1); |
| } |
| |
| struct sockaddr_in servaddr; |
| memset(&servaddr, 0, sizeof(servaddr)); |
| servaddr.sin_family = AF_INET; |
| servaddr.sin_port = htons(9000); |
| servaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| |
| |
| int on = 1; |
| |
| if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ |
| perror("setsockopt error."); |
| exit(1); |
| } |
| |
| if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ |
| perror("bind error."); |
| exit(1); |
| } |
| |
| if(listen(listenfd, SOMAXCONN) < 0){ |
| perror("listen() error."); |
| exit(1); |
| } |
| |
| |
| struct sockaddr_in peeraddr; |
| socklen_t peerlen = sizeof(peeraddr); |
| int conn; |
| if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0){ |
| perror("accept() error"); |
| exit(1); |
| } |
| printf("ip = %s, port = %d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); |
| |
| pid_t pid; |
| pid = fork(); |
| if(pid == -1){ |
| perror("fork() error"); |
| exit(1); |
| } |
| if(pid == 0){ |
| |
| |
| signal(SIGUSR1, handler); |
| char sendbuf[1024] = {0}; |
| while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){ |
| write(conn, sendbuf, strlen(sendbuf)); |
| memset(sendbuf, 0, sizeof(sendbuf)); |
| } |
| exit(EXIT_SUCCESS); |
| } else { |
| |
| char recvbuf[1024]; |
| while (1){ |
| memset(recvbuf, 0, sizeof(recvbuf)); |
| int ret = read(conn, recvbuf, sizeof(recvbuf)); |
| if(ret == -1){ |
| perror("read error"); |
| exit(1); |
| } else if(ret == 0){ |
| printf("peer close\n"); |
| break; |
| } |
| fputs (recvbuf, stdout); |
| } |
| kill(pid, SIGUSR1); |
| exit(EXIT_SUCCESS); |
| } |
| return 0; |
| } |
实验结果

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)