Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

基于TCP的简易聊天室系统

$
0
0

//TCP聊天室客户端

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <string.h>

#include <signal.h>

char* IP = "127.0.0.1";

//获取本机IP(回送地址--主要用于网络软件测试或本机进程间通信)

short PORT = 10222;//端口

typedef struct sockaddr SA;//用做类型转换

int sockfd = 0;

char name[20] = {};

//1、启动客户端,连接服务器

void init(){

printf("聊天室客户端开始启动..\n");

sockfd = socket(PF_INET,SOCK_STREAM,0);

struct sockaddr_in addr;

addr.sin_family = PF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = inet_addr(IP);

//连接

if(connect(sockfd,(SA*)&addr,sizeof(addr))==-1){

perror("无法连接服务器");

printf("客户端启动失败\n");

exit(-1);

}

printf("客户端启动成功\n");

}

//2、开始通信

void start(){

//主要是来发送消息

//发消息之前,启动一个线程,用来接收消息

pthread_t pid;

void* recv_thread(void*);//线程函数声明

pthread_create(&pid,0,recv_thread,0);

while(1){

char buf[100] = {};

scanf("%s",buf);//读取客户的输入

char msg[200] = {};

sprintf(msg,"%s :%s",name,buf);

send(sockfd,msg,strlen(msg),0);

}

}

//线程函数,用来接收消息

void* recv_thread(void* p){

while(1){

char buf[200] = {};

if(recv(sockfd,buf,sizeof(buf),0)<=0){

return ;//结束线程

}

printf("%s\n",buf);

}

}

void sig_close(){

//关闭客户端的socket

close(sockfd);

exit(0);

}

int main(){

signal(SIGINT,sig_close);

printf("请输入昵称:");

scanf("%s",name);

init();//启动客户端连接到服务器

send(sockfd,name,strlen(name),0);

start();

}

 

//TCP聊天室服务器

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <string.h>

#include <signal.h>

char* IP = "127.0.0.1";

//获取本机IP(回送地址--主要用于网络软件测试或本机进程间通信)

short PORT = 10222;//端口

typedef struct sockaddr SA;//用做类型转换

struct client {

char name[20]; //记录客户端昵称

int fds; //记录客户端socket描述符

};

struct client c[100] = {0}; //记录客户端结构数组,最多记录100

int size = 0;//用来记录客户端个数,遍历数组

int sockfd = 0;

//1.初始化服务器网络,创建socket

void init() {

printf("聊天室的服务器开始启动\n");

sockfd = socket(PF_INET,SOCK_STREAM,0);

if(sockfd == -1) perror("socket"),exit(-1);

struct sockaddr_in addr;

addr.sin_family = PF_INET;

addr.sin_port   = htons(PORT);

addr.sin_addr.s_addr = inet_addr(IP);

if(bind(sockfd,(SA*)&addr,sizeof(addr))==-1){

perror("绑定失败");

printf("服务器启动失败\n");

exit(-1);

}

printf("绑定成功\n");

if(listen(sockfd,100) == -1){

perror("设置监听失败");

printf("服务器启动失败\n");

exit(-1);

}

printf("设置监听成功\n");

//等待客户端连接写到另一个函数中

printf("初始化服务器成功\n");

}

//辅助函数,用来分发消息

void sendMsgToAll(char* msg){

int i = 0;

for(i=0;i<size;i++){

printf("sendto%d\n",c[i].fds);

send(c[i].fds,msg,strlen(msg),0);

}

}

//线程函数,用来接受客户发过来的消息,并且把消息发给所有客户端

void* service_thread(void* p){

int fd = *(int*)p;//拿到客户端的socket描述符

printf("pthread=%d\n",fd);//线程对应客户端

//保留客户端的信息

c[size].fds = fd;

char name[20]={};

if(recv(fd,name,sizeof(name),0)>0){//接受昵称

strcpy(c[size].name,name);

}

size++;

//先群发一条消息,表示欢迎,也可以通知其他客户端有人进入聊天室

char tishi[100]={};

sprintf(tishi,"热烈欢迎 %s 登录本聊天室..",name);

//把这条消息发给所有人

sendMsgToAll(tishi);

//通信部分,收发消息

while(1){

char buf[200] = {};

if(recv(fd,buf,sizeof(buf),0)==0){//接受消息

printf("fd=%dquit\n",fd);

//有客户端断开

int i;

char name[20]={};

for(i=0;i<size;i++){

if(c[i].fds == fd){

strcpy(name,c[i].name);

c[i].fds = c[size-1].fds;

strcpy(c[i].name,c[size-1].name);

}

}

size--;

printf("quit->fd=%dquit\n",fd);

char msg[100] = {};

sprintf(msg,"欢送 %s 离开聊天室,再见!",name);

sendMsgToAll(msg);

close(fd);//关闭描述符

return;//客户端退出了,结束线程

}

sendMsgToAll(buf);//成功接受到消息,就直接发给所有客户端

}

}

 

//等待客户端连接,启动服务器的服务

void service(){

printf("服务器开始服务\n");

while(1){

struct sockaddr_in fromaddr;//存储客户端的通信地址信息

socklen_t len = sizeof(fromaddr);

int fd = accept(sockfd,(SA*)&fromaddr,&len);

if(fd == -1){

printf("客户端连接出错\n");

continue;//继续下一次循环,处理连接

}

//如果客户成功连接

//开启线程,为该客户端进行服务

printf("fd=%d\n",fd);

pthread_t pid;

pthread_create(&pid,0,service_thread,&fd);

}

}

void sig_close(){

//关闭socket

int i = 0;

for(;i<size;i++){

if(c[i].fds != 0){

close(c[i].fds);

}

}

close(sockfd);//服务器的socket

printf("服务器已经关闭..\n");

exit(0);

}

int main(){

signal(SIGINT,sig_close);//做好善后工作

init();

service();

return 0;

}

 

作者:u012311875 发表于2013-12-20 23:57:47 原文链接
阅读:131 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>