linux聊天室程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux C-多线程的聊天室一.多线程与进程:
线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
每个应用对应一个进程。而一个进程包含至少一个线程,线程要和cpu进行交互。
多线程并发:“同一时间”执行多件事情,如程序一边执行,一边计时。多线程并发的本质:并不是cpu“同时”执行多件事情,而是在不停的切换,执行一段时间事件A,切换,执行时间事件B;再切换,再执行,如此往复。
线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针,程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
多线程是指程序中包含多个程序执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是允许单个程序创建多个并行执行的线程来完成各自的任务。
二.聊天室功能:
实现多用户群体聊天功能(此程序最多设定为10人),每个人所发送的消息其他用户均可以收到。用户可以随意的加入或退出。
三.所用函数:
创建
int socket(int domain, int type, int protocol);
domain:协议域。协议族决定了socket的地址类型,在通信中必须采用对应的地址。
type:指定Socket类型。常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。
protocol:指定协议。
绑定
int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);
参数说明:
socket:是一个套接字描述符。
address:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号。
address_len:确定address缓冲区的长度。
接收
int recv(SOCKET socket, char FAR* buf, int len, int flags);
socket:一个标识已连接套接口的描述字。
buf:用于接收数据的缓冲区。
len:缓冲区长度。
flags:指定调用方式。取值:MSG_PEEK 查看当前数据,数据将被复制到缓冲区中,但并不从输入队列中删除;MSG_OOB 处理带外数据。
网络监听
int listen(SOCKET sockfd, int backlog);
sockfd一个已绑定未被连接的套接字描述符
backlog 连接请求队列的最大长度(一般由2到4)
接收连接请求
int accept( int fd, struct socketaddr* addr, socklen_t* len);
fd:套接字描述符。
addr:返回连接着的地址
len:接收返回地址的缓冲区长度
四.服务器端
1.程序结构:总共有三个函数:主函数(main),实现服务器端的初始化,接受连接;消息处理函数(RC_snd),接受某一用户的消息,将其进行简单处理之后发送给其他所有的用户;退出函数(quit),可实现服务器关停。这三个函数分别从属于三个线程:main
函数的作为主线程,又创建了一个退出函数所在的线程,以及每次接受到一个连接之后会新创建一个对此连接的消息进行处理的线程。
2.服务器端代码:
#define LISTENQ 5
#define MAXLINE 512
#define MAXMEM 10
#define NAMELEN 20
//分别记录服务器端的套接字与连接的多个客户端的套接字
int listenfd,connfd[MAXMEM];
//服务器关闭函数
void quit();
//服务器接收并转发消息函数 6
void rcv_snd(int n);
int main()
{
pthread_t thread;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
time_t ticks;
char buff[MAXLINE];
//调用socket函数创建服务器端的套接字
printf("Socket...\n");
listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
printf("Socket created failed.\n");
return -1;
}
//调用bind函数使得服务器端的套接字与地址实现绑定
printf("Bind...\n");
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr="127.0.0.1";
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
{
printf("Bind failed.\n");
return -1;
}
//调用listen函数,将一个主动连接套接字变为被动的倾听套接字
//在此过程中完成tcp的三次握手连接
printf("listening...\n");
listen(listenfd,LISTENQ);
//创建一个线程,对服务器程序进行管理(关闭)
pthread_create(&thread,NULL,(void*)(&quit),NULL);
//记录空闲的客户端的套接字描述符(-1为空闲)
int i=0;
for(i=0;i { connfd[i]=-1; } while(1) { len=sizeof(cliaddr); for(i=0;i { if(connfd[i]==-1) { break; } } //调用accept从listen接受的连接队列中取得一个连接 connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len); ticks=time(NULL); sprintf(buff,"% .24s \r \n",ctime(&ticks)); printf("%s Connect from:%s,port%d\n\n”, ,buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));