select 服务器
ubuntu@ubuntu:~/wlbc$ vi 2.c
ubuntu@ubuntu:~/wlbc$ gcc 2.c
ubuntu@ubuntu:~/wlbc$ cat 1.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
int main(int argc, const char *argv[])
{
int sfd =socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(8888);
sin.sin_addr.s_addr=inet_addr("192.168.8.111");
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
if( listen(sfd,128)<0)
{
ERR_MSG("listen");
return -1;
}
fd_set readfds;
fd_set tempfds;
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
FD_SET(0,&readfds);
FD_SET(sfd,&readfds);
int maxfd =sfd;
int s_res =0;
ssize_t res =0;
char buf[128] ="";
struct sockaddr_in cin;
socklen_t addrlen =sizeof(cin);
int newfd =0;
while(1)
{
tempfds =readfds ;
s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(s_res<0)
{
ERR_MSG("select");
return -1;
}
printf("__%d__",__LINE__);
for(int i =0 ;i<=maxfd;i++)
{
if(FD_ISSET(i,&tempfds)==0)
{
continue;
}
if(0==i)
{
printf("触发键盘输入事件\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
printf("%s\n",buf);
}
else if(i==sfd)
{
printf("触发了客户端连接事件\n");
newfd =accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd<0)
{
ERR_MSG("accept");
}
printf("[%s %d]newfd =%d 连接成功\n",inet_ntoa(cin.sin_addr),cin.sin_port,newfd);
FD_SET(newfd,&readfds);
maxfd =maxfd>newfd ? maxfd:newfd;
}
else
{
printf("触发客户端交互事件\n");
bzero(buf,sizeof(buf));
res =recv(i,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}
else if(0==res)
{
printf("[%s %d]客户端断开连接\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
close(i);
FD_CLR(i,&readfds);
int j=0;
for(j=maxfd;j>0;j--)
{
if(FD_ISSET(j,&readfds))
{
maxfd=j;
break;
}
}
}
else
{
printf("[%s %d]newfd %d %s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),i,buf);
}
}
}
}
close(newfd);
close(sfd);
return 0;
}
2.poll客户端
ubuntu@ubuntu:~/wlbc$ vi 2.c
ubuntu@ubuntu:~/wlbc$ cat 2.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <poll.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
int main(int argc, const char *argv[])
{
int sfd =socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(8888);
sin.sin_addr.s_addr=inet_addr("192.168.8.111");
if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("connect");
return -1;
}
struct pollfd fds[2];
fds[0].fd=0;
fds[0].events = POLLIN;
fds[1].fd=sfd;
fds[1].events =POLLIN;
ssize_t res =0;
char buf[128] ="";
struct sockaddr_in cin;
socklen_t addrlen =sizeof(cin);
int pres =0;
while(1)
{
pres =poll(fds,2,-1);
if(pres < 0)
{
ERR_MSG("poll");
return -1;
}
else if(pres == 0)
{
printf("time out\n");
break;
}
if(fds[0].revents&POLLIN)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
if(send(sfd,buf,sizeof(buf),0)<0)
{
ERR_MSG("send");
return -1;
}
printf("发送成功\n");
}
if(fds[1].revents & POLLIN)
{
res = recv(sfd,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(res == 0)
{
printf("服务器断开连接\n");
break;
}
printf("%s\n",buf);
}
}
close(sfd);
return 0;
}
3 select 客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
int main(int argc, const char *argv[])
{
int sfd =socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(8888);
sin.sin_addr.s_addr=inet_addr("192.168.8.111");
if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("connect");
return -1;
}
fd_set readfds;
fd_set tempfds;
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
FD_SET(0,&readfds);
FD_SET(sfd,&readfds);
int maxfd =sfd;
int s_res =0;
ssize_t res =0;
char buf[128] ="";
struct sockaddr_in cin;
socklen_t addrlen =sizeof(cin);
int newfd = -1;
while(1)
{
tempfds =readfds ;
s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(s_res<0)
{
ERR_MSG("select");
return -1;
}
else if(s_res == 0)
{
fprintf(stderr,"客户端断开了\n");
break;
}
for(int i =0 ;i<=maxfd;i++)
{
if(FD_ISSET(i,&tempfds)==0)
{
continue;
}
if(0==i)
{
printf("触发键盘输入事件\n");
bzero(buf,sizeof(buf));
int sandfd;
int rbb = scanf("%d %s",&sandfd,buf);
if(rbb !=2 )
{
ERR_MSG("scanf");
continue;
}
printf("[%s %d]newfd =%d",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),i);
if(FD_ISSET(sandfd,&readfds) == 0)
{
printf("不在读集合里面\n");
continue;
}
if(send(sfd,buf,sizeof(buf),0)<0)
{
ERR_MSG("send");
return -1;
}
}
else if(i==sfd)
{
printf("触发了客户端连接事件\n");
newfd =accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd<0)
{
ERR_MSG("accept");
}
printf("[%s %d]newfd =%d 连接成功\n",inet_ntoa(cin.sin_addr),cin.sin_port,newfd);
FD_SET(newfd,&readfds);
maxfd =maxfd>newfd ? maxfd:newfd;
}
else
{
printf("触发客户端交互事件\n");
bzero(buf,sizeof(buf));
res =recv(i,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}
else if(0==res)
{
printf("[%s %d]客户端断开连接\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
close(i);
FD_CLR(i,&readfds);
int j=0;
for(j=maxfd;j>0;j--)
{
if(FD_ISSET(j,&readfds))
{
maxfd=j;
break;
}
}
}
else
{
printf("[%s %d]newfd %d %s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),i,buf);
}
}
}
}
close(newfd);
close(sfd);
return 0;
}
udp聊天室
服务器
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#define ERR_MSG(msg) do {\
fprintf(stderr,"_%d_",__LINE__);\
perror(msg);\
}while(0)
int sfd;//不能初始化为0,因为文件描述符0 1 2已经存在
//定义一个链表来存放用户信息
typedef struct node
{
union
{
int len;
struct sockaddr_in nin;
};
struct node *next;
}list;
struct sockaddr_in cin;
socklen_t addrlen =sizeof(cin);
char buf[128]="";
typedef struct user
{
int num;
char name[20];
char data[128];
}User;
User user;
int main(int argc, const char *argv[])
{
//创建套接字
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许发送广播
int broad =1;
if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&broad,sizeof(broad))<0)
{
ERR_MSG("setsockopt");
return -1;
}
// 填充信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = ntohs(8888);
sin.sin_addr.s_addr = inet_addr("192.168.43.255");
//绑定信息
//
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
list *l =(list*)malloc(sizeof(list));
if(l==NULL)
{
ERR_MSG("malloc");
return -1;
}
l->len =0;
l->next =NULL;
list *p=NULL;
list *q=NULL;
ssize_t res =0;
while(1)
{
res =recvfrom(sfd,&user,sizeof(user),0,(struct sockaddr*)&cin,&addrlen);
if(res<0)
{
ERR_MSG("recvform");
return -1;
}
else if(res >0)
{
printf("读取成功\n");
if(user.num==1)
{
printf("[%s %d]\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
p=(list*)malloc(sizeof(list));
if(p==NULL)
{
ERR_MSG("malloc");
return -1;
}
//头插
p->next = l->next;
p->nin = cin;
l-> next = p;
l->len++;
q=l->next;
user.num =4;
while(q!=NULL)
{
if(sendto(sfd,&user,sizeof(user),0,(struct sockaddr*)&q->nin,sizeof(q->nin))<0)
{
ERR_MSG("sendto");
return -1;
}
q=q->next;
}
}else if(user.num==2)
{
printf("[%s %d]\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
if(strcmp(user.data,"quit")==0)
{
user.num =3;
strcpy(user.data,"退出啦");
q=l->next;
while(q!=NULL)
{
if(sendto(sfd,&user,sizeof(user),0,(struct sockaddr*)&q->nin,sizeof(q->nin))<0)
{
ERR_MSG("sendto");
return -1;
}
q=q->next;
}
p=l;
while(p->next != NULL)
{
if(p->next->nin.sin_port == cin.sin_port)
{
q=p->next->next;
free(p->next);
p->next = q;
break;
}
p=p->next;
}
}else
{
user.num=3;
q=l->next;
while(q!=NULL)
{
if(sendto(sfd,&user,sizeof(user),0,(struct sockaddr*)&q->nin,sizeof(q->nin))<0)
{
ERR_MSG("sendto");
return -1;
}
q=q->next;
}
}
}
}
}
close(sfd);
return 0;
;
}
udp的客户端
ubuntu@ubuntu:~/wlbc/day6$
ubuntu@ubuntu:~/wlbc/day6$ cat udp02.c
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#define ERR_MSG(msg) do {\
fprintf(stderr,"_%d_",__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.43.170"
//#define PORT 8888 // 1024~49151
typedef struct MSG{
int num;
char name[20];
char data[256];
}User;
int sfd;
struct sockaddr_in cin;
socklen_t addrlen= sizeof(cin);
User user;
char cname[20];
void *recv1(void*arg)
{
while(1)
{
if(recv(sfd, &user, sizeof(user),0) < 0)
{
ERR_MSG("recvfrom");
return NULL;
}
if (strcmp(user.name,cname)!=0) //判断是否为自己发送的
{
if(user.num==3)
{
printf("%s:%s\n",user.name,user.data);
}
if (user.num==4)
{
printf("%s进入聊天室\n",user.name);
}
}
}
pthread_exit(NULL);
}
void *send1(void*arg)
{
while(1)
{
scanf("%s",user.data);
user.num=2;
strcpy(user.name,cname);
if(sendto(sfd, &user, sizeof(user), 0, (struct sockaddr*)&cin, sizeof(cin)) < 0)
{
ERR_MSG("recvfrom");
return NULL;
}
if (strcmp(user.data,"quit")==0)
{
exit(0);
}
}
pthread_exit(NULL);
}
//绑定一个广播ip的端口试试
int main(int argc, const char *argv[])
{
//创建报式套接字
sfd =socket(AF_INET,SOCK_DGRAM,0);
if (sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
int broad =1;
if (setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&broad,sizeof(broad))<0)
{
ERR_MSG("setsockopt");
return -1;
}
//填充地址信息结构体,真实的地址信息结构体与协议族有关
//AF_INEt 详见 man 7 ip
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(8888);//主机字节序转网络字节序的端口号
sin.sin_addr.s_addr = inet_addr("192.168.43.255");
cin = sin;
int port = atoi(argv[1]);
struct sockaddr_in bin;
bin.sin_family =AF_INET;
bin.sin_port =htons(port);//主机字节序转网络字节序的端口号
bin.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&bin,sizeof(bin))==-1)
{
ERR_MSG("bind");
return -1;
}
ssize_t res=0;
printf("请输入用户名:");
scanf("%s",user.name);
user.num=1;//num为1时内容为名字
strcpy(cname,user.name);
sendto(sfd,&user,sizeof(user),0,(struct sockaddr*)&sin, addrlen);
user.num=2; //num为2时内容为聊天内容
//将客户端的收发分别写入两个线程,这样就可以同时运行
pthread_t tid1,tid2;
if (pthread_create(&tid1,NULL,recv1,NULL)!=0)
{
ERR_MSG("pthread_create");
return -1;
}
if (pthread_create(&tid2,NULL,send1,NULL)!=0)
{
ERR_MSG("pthread_create");
return -1;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
close(sfd);
return 0;
}