Linux用多线程和socket实现跨机器的聊天通信功能

2019-07-12 21:10发布

这样写还是回有些问题,比如说子线程退出后由于父线程没有join导致的资源未释放,还有就是客户端可以无限制得增加,因为每增加一个客户端就会有两个服务端线程被创建,所以要控制一下,避免过的的消耗资源,在下个博客里面这些问题都会改进 客户端代码如下 #include #include #include #include #include #include #include #include #include void* recvsocket(void *arg) { int st = *(int *)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); int rc = recv(st, s, sizeof(s), 0); if (rc <= 0) break; printf("%s ", s); } return NULL; } void* sendsocket(void *arg) { int st = *(int *)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); read(STDIN_FILENO, s, sizeof(s)); send(st, s, strlen(s), 0); } return NULL; } int main(int arg, char *args[]) { if (arg < 3) { return -1; } int port = atoi(args[2]); int st = socket(AF_INET, SOCK_STREAM, 0);//初始化socket struct sockaddr_in addr; // 定义一个IP地址的结构 memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET;// 设置结构地址类型为TCP/IP地址 addr.sin_port = htons(port); // 制定一个端口号:8080,htons:将short类型从host字节类型转到net字节类型 // 将字符类型的IP地址转化为int,赋给addr结构 //addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_addr.s_addr = inet_addr(args[1]); // if (connect(st, (struct sockaddr *)&addr, sizeof(addr)) == -1) { printf("connect failed %s ", strerror(errno)); return EXIT_FAILURE; } pthread_t thrd1, thrd2; pthread_create(&thrd1, NULL, recvsocket, &st); pthread_create(&thrd2, NULL, sendsocket, &st); pthread_join(thrd1, NULL); pthread_join(thrd2, NULL); close(st); return EXIT_SUCCESS; }
服务端的代码如下 #include #include #include #include #include #include #include #include #include #include void* recvsocket(void *arg) { int st = *(int *)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); int rc = recv(st, s, sizeof(s), 0); if (rc <= 0) break; printf("%s ", s); } return NULL; } void* sendsocket(void *arg) { int st = *(int *)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); read(STDIN_FILENO, s, sizeof(s)); send(st, s, strlen(s), 0); } return NULL; } int main(int arg, char *args[]) { if (arg < 2) { return -1; } int port = atoi(args[1]); int st = socket(AF_INET, SOCK_STREAM, 0); //初始化socket int on = 1; if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { printf("setsockopt failed %s ", strerror(errno)); return EXIT_FAILURE; } struct sockaddr_in addr; // 定义一个IP地址结构 memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; // 将addr结构的属性定位为TCP/IP地址 addr.sin_port = htons(port); // 将本地字节顺序转化为网络字节顺序 addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY代表这个server上所有的地址 // 将ip与server程序绑定 if (bind(st, (struct sockaddr *) &addr, sizeof(addr)) == -1) { printf("bind failed %s ", strerror(errno)); return EXIT_FAILURE; } // server端开始listen if (listen(st, 20) == -1) { printf("listen failed %s ", strerror(errno)); return EXIT_FAILURE; } //printf("listen success "); int client_st = 0; struct sockaddr_in client_addr; // 表示client端的IP地址 pthread_t thrd1, thrd2; while (1) { memset(&client_addr, 0, sizeof(client_addr)); socklen_t len = sizeof(client_addr); client_st = accept(st, (struct sockaddr*) &client_addr, &len); if (client_st == -1) { printf("accept failed %s ", strerror(errno)); return EXIT_FAILURE; } printf("accept by %s ", inet_ntoa(client_addr.sin_addr)); pthread_create(&thrd1, NULL, recvsocket, &client_st); pthread_create(&thrd2, NULL, sendsocket, &client_st); } close(st); return 0; }makefile文件如下 .SUFFIXES: .c .o CC=gcc ASRCS=sock.c BSRCS=server.c AOBJS=$(ASRCS:.c=.o) BOBJS=$(BSRCS:.c=.o) AEXEC=client BEXEC=server all:$(AOBJS) $(BOBJS) $(CC) -o $(AEXEC) $(AOBJS) -lpthread $(CC) -o $(BEXEC) $(BOBJS) -lpthread @echo '-------------ok--------------' .c.o: $(CC) -Wall -g -o $@ -c $< clean: rm -f $(AOBJS) rm -f $(BOBJS) rm -f core*