這個可以實現羣發消息,客戶端連接上後發送的消息除了自己其他客戶端都可以看到
服務器端-C語言
頭文件
#include<unistd.h>
#include <netinet/in.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/select.h>
#include<sys/time.h>
#include<stdlib.h>
#include<limits.h>
#include<error.h>
#include<math.h>
#define MAXLINE 1024
char recvline[MAXLINE];
char sendline[MAXLINE];
主函數
#include"unp.h"
int main(int argc,char * argv[])
{
int i,maxi,maxfd,listenfd,connfd,sockfd,j;
int nready,client[FD_SETSIZE];
ssize_t n;
fd_set rset,allset;
char buf[MAXLINE],buf1[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr,servaddr;
listenfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(9880);
//servaddr.sin_addr.s_addr=htonl("127.0.0.1"); 爲啥不能用htonl
servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//測試的是自己本機,要想測其他本機記得改IP哦.
bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
listen(listenfd,5);
maxfd=listenfd;
maxi=-1;
for(i=0;i<FD_SETSIZE;i++)
client[i]=-1;
FD_ZERO(&allset);
FD_SET(listenfd,&allset);
for(;;)
{
rset=allset;
nready=select(maxfd+1,&rset,NULL,NULL,NULL);
if(FD_ISSET(listenfd,&rset))
{
clilen=sizeof(cliaddr);
connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);
printf("%d\n",connfd);
for(i=0;i<FD_SETSIZE;i++)
{
if(client[i]<0)
{
client[i]=connfd;
break;
}
}
if(i==FD_SETSIZE)
perror("too many clients");
FD_SET(connfd,&allset);
if(connfd>maxfd)
maxfd=connfd;
if(i>maxi)
maxi=i;
if(--nready<=0)
continue;
}
for(i=0;i<=maxi;i++)
{
if((sockfd=client[i])<0)
continue;
if(FD_ISSET(sockfd,&rset))
{
#if 1
if( (n=read(sockfd,buf1,MAXLINE)) ==0)
{
close(sockfd);
FD_CLR(sockfd,&allset);
client[i]=-1;
}
else
{ //把客戶端的IP和信息寫進buf,發送給其他用戶
sprintf(buf,"%s-----%s",inet_ntoa(cliaddr.sin_addr),buf1);
for(j=0;j<=maxi;j++)
if(client[j]!=sockfd)
write(client[j],buf,strlen(buf)+1);
}
#endif
#if 0
if( (n=read(sockfd,buf,MAXLINE)) ==0)
{
close(sockfd);
FD_CLR(sockfd,&allset);
client[i]=-1;
}
else
{
for(j=0;j<=maxi;j++)
if(client[j]!=sockfd)
write(client[j],buf,n);
}
#endif
if(--nready<=0)
break;
}
}
}
return 0;
}
客戶端-C++
頭文件
#include<iostream>
using namespace std;
#include<algorithm>
#include<unistd.h>
#include <netinet/in.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/select.h>
#include<sys/time.h>
#include<stdlib.h>
#include<limits.h>
#include<error.h>
#include<math.h>
#define MAXLINE 1024
char recvline[MAXLINE];
char sendline[MAXLINE];
主函數
#include"util.h"
void str_cli(FILE *fp,int sockfd)
{
int maxfdp1,stdineof;
fd_set rset;
char buf[MAXLINE];
int n;
stdineof=0;
FD_ZERO(&rset);
char s1[1024],s2[1024];
for(;;)
{
if(stdineof==0)
FD_SET(fileno(fp),&rset);
FD_SET(sockfd,&rset);
maxfdp1=max(fileno(fp),sockfd)+1;
select(maxfdp1,&rset,NULL,NULL,NULL);
if(FD_ISSET(sockfd,&rset))
{
if((n=read(sockfd,buf,MAXLINE))==0)
{
if(stdineof==1)
return;
else
perror("strcli:server terminated prematurely");
}
sscanf(buf,"%s",s1);
cout<<s1<<" "<<endl;
//write(fileno(stdout),buf,n);
}
if(FD_ISSET(fileno(fp),&rset))
{
if((n=read(fileno(fp),buf,MAXLINE))==0)
{
stdineof=1;
shutdown(sockfd,SHUT_WR);
FD_CLR(fileno(fp),&rset);
continue;
}
write(sockfd,buf,n);
}
}
}
int main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
if(argc!=2)
perror("usage:tcpcli <IPadress>");
sockfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(9880);
inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
str_cli(stdin,sockfd);
exit(0);
}
遇到的問題:
1.#include<netinet/in.h>這個頭文件還是不太懂它是哪個結構體或函數需要引入;看別人說struct sockaddr這和結構體需要
2.servaddr.sin_addr.s_addr=htonl(“127.0.0.1”); 會報錯,不懂.
3.sprintf(buf,”%s\t\t%s”,inet_ntoa(cliaddr.sin_addr),buf1);
寫’\t\t’發的信息會出現亂碼;
sprintf(buf,”%s %s”,inet_ntoa(cliaddr.sin_addr),buf1);
寫成空格運行不了. 不是很懂.
編譯:
gcc server.c -o server
g++ client.c -o client
./server
./client
運行結果
第一個用戶
第二個用戶