1.目标
在实现回声服务器和客户端后 ,基于多线程设计一对一的聊天室
2.功能
在本机上实现客户端与服务器的实时聊天测试 以达到练习强化socket通信/多线程技术的目的
3.测试
客户端主线程 与两个子线程
服务器主线程 与两个子线程
能够相互收到信息 并且进行应答
最后关闭socket
代码如下:
客户端:
#include#include #include #include #include #include #include #include #include #include #define BUF_SIZE 1024 #define SERVER_PORT 666 #define SERVER_IP "127.0.0.1" char buf_send[BUF_SIZE]={0}; char buf_recv[BUF_SIZE]={0}; //发送线程功能函数 void * sendMsg(void * socket){ int *client_sock = (int *)socket; while(1){ scanf("%s",buf_send);//buf_send表示数组元素首地址 此时再往里边输入数据 会覆盖掉原数据 send(*client_sock, buf_send, strlen(buf_send), 0);//因为第一个形参传过来的是个地址所以加*号才是int //退出发送 if(!strncasecmp(buf_send, "quit", 4)){ //该函数就是对比第一个字符串和第二个字符串 的前4个字符是否相等 相等返回零 break; } } pthread_exit(NULL); } //接受线程功能函数 void * recvMsg(void * socket){ int *client_sock = (int *)socket; while(1){ bzero(buf_recv, BUF_SIZE);//先把buf清零 if(recv(*client_sock, buf_recv, BUF_SIZE, 0)>0){ printf("Msg from server: %sn", buf_recv); } if(!strncasecmp(buf_send, "quit", 4)){ //该函数就是对比第一个字符串和第二个字符串 的前4个字符是否相等 相等返回零 break; } } pthread_exit(NULL); } //客户端首先创建一个socket //绑定想要连接的服务器的IP和端口号 然后调用connect函数通过socket去连接服务器 int main() { int sockfd; struct sockaddr_in servaddr; int n; sockfd=socket(AF_INET, SOCK_STREAM, 0); memset(&servaddr, ' ', sizeof(struct sockaddr_in)); //此处需要标明服务器的IP和端口 servaddr.sin_family=AF_INET; //将IP和端口号进行转化 转化为网络字节序 就是socket函数使用的IP和端口格式 inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr); servaddr.sin_port = htons(SERVER_PORT); if((connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))>=0){ printf("连接成功!n"); } if((recv(sockfd, buf_recv, BUF_SIZE, 0))>0){ printf("message from server: %sn", buf_recv); } //创建线程用于收发 pthread_t send_tid, recv_tid; pthread_create(&send_tid, NULL, sendMsg, (void *)&sockfd); pthread_create(&recv_tid, NULL, recvMsg, (void *)&sockfd); //此函数表示 子线程 结束 才能执行 主线程中后边的函数(防止子线程被中断) pthread_join(send_tid, NULL); pthread_join(recv_tid, NULL); close(sockfd); return 0; }
服务器:
#include#include #include #include #include #include #include #include #include #define SERVER_PORT 666 #define BUF_SIZE 1024 char buf_send[BUF_SIZE] = "connection succeeded"; char buf_recv[BUF_SIZE]; //发送线程功能函数 void * sendMsg(void * socket){ int *client_sock = (int *)socket; while(1){ scanf("%s",buf_send);//buf_send表示数组元素首地址 此时再往里边输入数据 会覆盖掉原数据 send(*client_sock, buf_send, strlen(buf_send), 0);//因为第一个形参传过来的是个地址所以加*号才是int //退出发送 if(!strncasecmp(buf_send, "quit", 4)){ //该函数就是对比第一个字符串和第二个字符串 的前4个字符是否相等 相等返回零 break; } } pthread_exit(NULL); } //接受线程功能函数 void * recvMsg(void * socket){ int *client_sock = (int *)socket; while(1){ bzero(buf_recv, BUF_SIZE);//先把buf清零 if(recv(*client_sock, buf_recv, BUF_SIZE, 0)>0){ printf("Msg from client: %sn", buf_recv); } if(!strncasecmp(buf_send, "quit", 4)){ //该函数就是对比第一个字符串和第二个字符串 的前4个字符是否相等 相等返回零 break; } } pthread_exit(NULL); } int main() { int sock;//信箱 int i; struct sockaddr_in server_addr; sock = socket(AF_INET, SOCK_STREAM, 0);//创建信箱 bzero(&server_addr,sizeof(server_addr));//清空标签 server_addr.sin_family=AF_INET;//选择协议族 server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//监听本地所有IP server_addr.sin_port=htons(SERVER_PORT);//绑定端口号 bind(sock,(struct sockaddr *)&server_addr,sizeof(server_addr));//绑定IP和端口 listen(sock,128);//监听客户端 printf("等待客户端的连接n"); struct sockaddr_in client; int client_sock, len; char client_ip[32];//用来存客户端IP和端口 打印 // char buf[256];//用来接客户端的数据 socklen_t client_addr_len; client_addr_len = sizeof(client); client_sock = accept(sock, (struct sockaddr*)&client, &client_addr_len); printf("client ip:%st port:%dn", inet_ntop(AF_INET,&client.sin_addr.s_addr,client_ip,sizeof(client_ip)), ntohs(client.sin_port)); send(client_sock, buf_send, strlen(buf_send), 0);//建立连接成功,给客户端发一条信息 //创建线程用于收发 pthread_t send_tid, recv_tid; pthread_create(&send_tid, NULL, sendMsg, (void *)&client_sock); pthread_create(&recv_tid, NULL, recvMsg, (void *)&client_sock); //此函数表示 子线程 结束 才能执行 主线程中后边的函数(防止子线程被中断) pthread_join(send_tid, NULL); pthread_join(recv_tid, NULL); close(client_sock); close(sock); printf("finshed!n"); return 0; }
重点:编译的时候 一定要加 -lpthread (多线程)
结果:后边有时间会接着改进,调试多人聊天模式, 有兴趣的可以一起来讨论交流, 待续。。。



