linux c tcp通信,Linuxc之基于TCP通信聊天室

1.完成基于Tcp的客户端和服务器程序编写;要求服务器采用并发方式,至少能同时接受3个客户端发送的数据;

源代码:

Server.c

#include#include#include#include#include#include#include#include#include#include#include#include#include#include

#define LISTENQ 1000 //最大连接数

#define MAXLINE 512  //发送消息的最长字节

#define MAXMEM  1000

#define NAMELEN 20   //名字长度

struct socketcfd

{

char name[20];

int fd;

};

int listenfd;                 //分别记录服务器端的套接字与连接的多个客户端的套接字

struct socketcfd connfd[MAXMEM];

void rcv_snd(void *arg)        //服务器接受并转发消息函数

{

char* ask="请输入你的名字:";

char* ask1="使用说明:\n1、群聊可以直接发送消息,\n2、退出直接输入“bye”\n-------------------------------------------";

char* ch="此用户不存在";

char* ch1="群聊";

char buff[MAXLINE];          //用户姓名

char buff1[MAXLINE];         //聊天内容(包括私聊和群聊,然后对它进行分析)

char buff2[MAXLINE];         //发送消息的时间

time_t ticks;

int i=0;

int retval;

int len;

int k=0,j=0,m=0;

int p;

int n=(int *)arg;

//获取此进程对应的套接字用户的名字

write(connfd[n].fd,ask,strlen(ask));

len=read(connfd[n].fd,connfd[n].name,NAMELEN);

if(len>0){

connfd[n].name[len]=0;

}

printf("用户姓名:%s\n",connfd[n].name);

//把当前用户的加入告知所有用户

strcpy(buff,connfd[n].name);

strcat(buff,"\t加入聊天");

for(i=0;iif(connfd[i].fd!=-1)

write(connfd[i].fd,buff,strlen(buff));

}

//告诉用户使用规则

write(connfd[n].fd,ask1,strlen(ask1));

//接受当前用户的信息并将其转发给所有用户或者指定用户

while(1){

if((len=read(connfd[n].fd,buff1,MAXLINE))>0)

{

buff1[len]=0;

//当前用户的输入信息为“bye”时,当前用户退出

if(strcmp("bye",buff1)==0){

printf("%s用户已退出\n",connfd[n].name);

close(connfd[n].fd);

connfd[n].fd=-1;

pthread_exit(&retval);

}

ticks=time(NULL);

sprintf(buff2,"%.25s\r\n",ctime(&ticks));

strcpy(buff,buff2);

strcat(buff,ch1);

strcat(buff,"\t");

strcat(buff,connfd[n].name);

strcat(buff,"\n");

strcat(buff,buff1);

for(i=0;iif(connfd[i].fd!=-1){

write(connfd[i].fd,buff,strlen(buff));

}

}

}

}

}

void quit()          //服务器关闭函数

{

char msg[10];

while(1){

scanf("%s",msg);

if(strcmp("quit",msg)==0){

printf("......服务器退出.....\n");

close(listenfd);

exit(0);

}

}

}

int main()

{

int fd;

pthread_t thread1,thread2;

struct sockaddr_in servaddr,cliaddr;

socklen_t len;

time_t ticks;

char buff[MAXLINE];

char addr_p[INET_ADDRSTRLEN];

int n=0;

//调用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(8080);

servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

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(&thread1,NULL,(void*)(&quit),NULL);

//记录空闲的客户端的套接字描述符(-1为空闲)

int i=0;

for(i=0;iconnfd[i].fd=-1;

}

while(1){

len=sizeof(cliaddr);

for(i=0;iif(connfd[i].fd==-1)

break;

}

//调用accept函数从listen接受的连接队列中取得一个连接

connfd[i].fd=accept(listenfd,(struct sockaddr*)&cliaddr,&len);

ticks=time(NULL);

sprintf(buff,"%.25s \r\n",ctime(&ticks));

inet_ntop(AF_INET,&cliaddr,addr_p,sizeof(addr_p));

printf("第%d个客户端连接成功\n",i+1);

printf("%s Connect from: %s,port %d\n",buff,addr_p,ntohs(cliaddr.sin_port));   //打印客户端连接的时间,地址和端口号

//针对当前套接字创建一个线程,对当前套接字的消息进行处理

pthread_create(&thread2,NULL,(void*)(&rcv_snd),(void*)i);

}

pthread_join(thread2,NULL);

pthread_join(thread1,NULL);

close(fd);

return 0;

}

Clinet.c

#include#include#include#include#include#include#include#include#include#include#include

#define MAXLINE 512

#define NAMELEN 20

#define PORT 8080

int sockfd;

//发送消息的函数snd

void snd()

{

char name[NAMELEN];

char buff[MAXLINE];

gets(name);

write(sockfd,name,strlen(name));

while(1)

{

gets(buff);

write(sockfd,buff,strlen(buff));

if(strcmp("bye",buff)==0)

{

exit(0);

}

}

}

int main(int argc,char **argv)

{

pthread_t thread;

struct sockaddr_in servaddr;

if(argc != 2)

{

printf("usage: echo ip\n");

return -1;

}

//调用socket函数创建客户端的套接字

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd<0)

{

printf("Socket create failed\n");

return -1;

}

//初始化服务器端的地址

servaddr.sin_family=AF_INET;

servaddr.sin_port=htons(PORT);

if(inet_aton(argv[1],&servaddr.sin_addr)<0)

{

printf("inet_aton error.\n");

return -1;

}

//调用connect函数实现与服务器端建立连接

printf("Connecting...\n");

if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)

{

printf("Connect server failed.\n");

return  -1;

}

//从此处开始程序分做两个线程

//创建发送消息的线程,调用了发送消息的函数snd

pthread_create(&thread,NULL,(void*)(&snd),NULL);

//从此处开始向下为接收消息的线程

char buff[MAXLINE];

int len;

while(1)

{

if((len=read(sockfd,buff,MAXLINE))>0)

{

buff[len]=0;

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

}

}

return 0;

}

详情请见本人上篇博客:点击打开链接

https://blog.csdn.net/qq_37192076/article/details/80778560

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值