使用之前的函数实现的简单聊天程序
TCP协议
双方实时发送/接收消息
实现后的问题:
可能是我虚拟机的IP地址配得有问题吧。在一台电脑上面开两个终端,用127.0.0.1的IP收发可以互通。但是两个虚拟机就不行了,用192.168的IP段,能够ping通但是代码接收不到消息。
还有,两个进程都是接收到消息后,需要我自己按一下回车才能发送消息。
服务器端代码:
#include<stdio.h> #include<string.h> #include<errno.h> #include<sys/socket.h> #include<resolv.h> #include<stdlib.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> #define MAXBUF 1024 int main(int argc, char *argv[]) { int pid; int sockfd, new_fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; if(argv[2]) myport = atoi(argv[2]); //命令行字符串转为整数,端口 else myport = 7575; //默认端口 if(argv[3]) lisnum = atoi(argv[3]); //监听队列的大小 else lisnum = 5; //创建socket对象, IPv4, TCP, 默认协议 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) //创建socket对象 { perror("socket"); exit(EXIT_FAILURE); } bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; //地址协议 my_addr.sin_port = htons(myport); //地址端口 if(argv[1]) my_addr.sin_addr.s_addr = inet_addr(argv[1]); //指定IP地址 从点分十进制字符串转为32位二进制 else my_addr.sin_addr.s_addr = INADDR_ANY; //否则设置为本机任意地址 char mybuf[128]; inet_ntop(AF_INET, &my_addr.sin_addr.s_addr, mybuf, 128); printf("the ip is '%s'\n", mybuf); //绑定地址信息 if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(EXIT_FAILURE); } //监听网络 if(listen(sockfd, lisnum) == -1) { perror("listen"); exit(EXIT_FAILURE); } printf("wait for connect\n"); len = sizeof(struct sockaddr); //阻塞等待连接 if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) == -1) { perror("accept"); exit(EXIT_FAILURE); } else //打印接收到的信息 { printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); } //创建新进程 if(-1 == (pid = fork())) { perror("fork"); exit(EXIT_FAILURE); } else if(0 == pid) //子进程用于发送消息 { while(1) { bzero(buf, MAXBUF + 1); printf("input the message to send:"); fgets(buf, MAXBUF, stdin); if(!strncasecmp(buf, "quit", 4)) { printf("i will close the connect!\n"); break; } len = send(new_fd, buf, strlen(buf) - 1, 0); if(len < 0) { printf("message '%s' send failure! errno code is %d, errno message is '%s'\n", buf, errno, strerror(errno)); break; } } } else //父进程用于接收消息 { while(1) { bzero(buf, MAXBUF + 1); len = recv(new_fd, buf, MAXBUF, 0); if(len > 0) { printf("message recv successful : '%s', %dByte recv\n", buf, len); } else if(len < 0) { printf("recv failure! errno code is %d, errno message is '%s'\n", errno, strerror(errno)); break; } else { printf("the other one close quit\n"); break; } } } close(new_fd); close(sockfd); return 0; }
客户端代码:
#include<stdio.h> #include<string.h> #include<errno.h> #include<sys/socket.h> #include<resolv.h> #include<stdlib.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> #define MAXBUF 1024 int main(int argc, char **argv) { int sockfd, len; struct sockaddr_in dest; char buffer[MAXBUF + 1]; if(argc != 3) { printf(" error format, it must be :\n \t\t%s IP port\n", argv[0]); exit(EXIT_FAILURE); } //创建socket对象 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket"); exit(errno); } printf("socket created\n"); bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; //地址协议 dest.sin_port = htons(atoi(argv[2])); //对方端口 //对方IP地址 if(inet_aton(argv[1], (struct in_addr *)&dest.sin_addr.s_addr) == 0) { perror("argv[1]"); exit(errno); } //发起连接 if(connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) == -1) { perror("Connect"); exit(errno); } printf("server connected\n"); pid_t pid; //创建子进程 if(-1 == (pid = fork())) { perror("fork"); exit(errno); } else if(pid == 0) //子进程用于数据接收 { while(1) { bzero(buffer, MAXBUF + 1); len = recv(sockfd, buffer, MAXBUF, 0); if(len > 0) { printf("recv successful:'%s', %d byte recv\n", buffer, len); } else if(len < 0) { perror("recv"); break; } else { printf("the other one close, quit\n"); break; } } } else //父进程用于数据发送 { while(1) { bzero(buffer, MAXBUF + 1); printf("input the message to send:"); fgets(buffer, MAXBUF, stdin); if(!strncasecmp(buffer, "quit", 4)) { printf("i will close the connect!\n"); break; } len = send(sockfd, buffer, strlen(buffer) - 1, 0); if(len < 0) { printf("message '%s' send failure! errno code is %d, errno message is '%s'\n", buffer, errno, strerror(errno)); break; } } } close(sockfd); return 0; }