从早上折腾到现在,基本上把聊天室的核心功能做出来了。
嗯,从下午到晚上一直在调试各种bug。
出现如下错误:
1、段错误(在使用链表的时候,非法使用p_last空间,解决方案是直接不用p_last)
2、新建的链表节点没有放在堆区…然后各种问题…
2、出现内存溢出(结果发现,第二次write一个/n的时候是copy的上一行的…第三个参数没改)——这个纠结了半下午。最后改成1,然后瞬间通畅…
3、关于服务器和客户端的线程回收(分离)的问题没关注,导致陷入printf("\n")的死循环…(解决方案是分别在客户端和服务器里加一个判断,如果从对方的通讯节点里收到的字节数为空,那么就直接关闭通讯节点并结束线程)
4.现在貌似还有个问题,就是我malloc堆区的内存还没有地方释放,我正在思考在哪里free…
先上传代码吧。明天再改改。
服务器端:server.c
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <ctype.h>
#include <stdlib.h>
typedef struct node{
int cfd;
struct node *p_next;
}node;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
node head={0};
node tail={0};
void* func(){
char buf[128];
// node* p_tmp=NULL;
pthread_mutex_lock(&mutex);
node* p_tmp=&head;
node* p_tmp1=&tail;
pthread_mutex_unlock(&mutex);
int cfd;
for(;p_tmp!=p_tmp1;p_tmp=p_tmp->p_next){
node* p_first = p_tmp;
node* p_mid = p_first->p_next;
if(p_mid == &tail){
cfd = p_first->cfd;
}
}
while(1){
pthread_mutex_lock(&mutex);
p_tmp=head.p_next;
pthread_mutex_unlock(&mutex);
bzero(buf,128);
int r=read(cfd,buf,128);
if(r==0){
printf("%d:关闭套接字,结束线程",cfd);
close(cfd);
pthread_exit(0);
}
for(;p_tmp!=p_tmp1;p_tmp=p_tmp->p_next){
node* p_first = p_tmp;
node* p_mid = p_first->p_next;
printf("%d:%s\n",cfd,buf);
write(p_first->cfd,buf,r);
printf("我发给了这个客户端:%d\n",p_first->cfd);
write(p_first->cfd,"\n",1);
}
}
return NULL;
}
int main(void){
struct sockaddr_in peer_addr;
socklen_t peer_addr_size;
peer_addr_size=sizeof(peer_addr);
int cfd;
char IP[64];
int sfd;
struct sockaddr_in my_addr;
node* p_node=NULL;
head.p_next = &tail;
tail.p_next = NULL;
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd == -1)
perror("socket");
memset(&my_addr, 0, sizeof(struct sockaddr_in));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(8080);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sfd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr_in)) == -1)
perror("bind");
if (listen(sfd, 5) == -1)
perror("listen");
pthread_t tid;
void* tret;
while(1){
node* p_newThread= (node*)malloc(sizeof(node));
p_newThread->cfd=accept(sfd,(struct sockaddr*)&peer_addr,&peer_addr_size);
p_newThread->p_next=NULL;
if(p_newThread->cfd==-1)perror("accept");
for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){
node* p_first = p_node;
node* p_mid = p_first->p_next;
if(p_mid==&tail){
p_first->p_next = p_newThread;
p_newThread->p_next = p_mid;
}
}
printf("%d\n",p_newThread->cfd);
printf("IP:%s\n",inet_ntop(AF_INET,
&peer_addr.sin_addr,IP,64));
pthread_create(&tid,NULL,func,NULL);
}
close(sfd);
return 0;
}
客户端:client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <strings.h>
#include <stdlib.h>
void* func(void* arg){
int fd=*(int*)arg;
char buf[128];
while(1){
bzero(buf,128);
int r=read(fd,buf,128);
if(r==0)break;
write(1,buf,r);
write(1,"\n",1);
bzero(buf,128);
}
exit(0);
return (void *)0;
}
int main(int argc,char* argv[]){
char msg[128];
struct sockaddr_in serv;
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd==-1){perror("socket");return -1;}
serv.sin_family=AF_INET;
serv.sin_port=htons(8080);
inet_pton(AF_INET,argv[1],&serv.sin_addr);
int c = connect(fd, (struct sockaddr*)&serv,sizeof(serv));
if(c==-1){perror("connect");return -1;}
while(1){
pthread_t tid;
pthread_create(&tid,NULL,func,&fd);
bzero(msg,128);
gets(msg);
write(fd,msg,strlen(msg));
}
return 0;
}
Ubuntu16.04和macOS10.13.2
实测已经成功。
也请大牛们多多指教啊。