#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define PORT 10086 //定义端口号为多少
void *dosth(void *arg); //线程调用函数
int main(void)
{
//先创建socket连接,规定好设备与设备之间的通讯协议为 IPV4 TCP 协议
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){
perror("socket error");
exit(-1);
}
//更改sockfd的属性,允许地址重复:防止报“地址重复”错误
int on = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定:设置好本地的通讯协议是什么,端口号和IP地址分别为多少
struct sockaddr_in myself;
myself.sin_family = AF_INET; //设置本地通讯协议为 IPV4 TCP 协议
myself.sin_port = htons(PORT); /*设置本地端口号,注意:由于PORT在本地为小端序,而网络传输需要用大端序来传输,所以这里需要用htons()函数来将PORT转换为大端序*/
myself.sin_addr.s_addr = htonl(INADDR_ANY); //设置本地的IP地址
if(bind(sockfd,(struct sockaddr *)&myself,sizeof(myself))){ //绑定本地属性,使用bind()函数,来让上面设置好的本地属性生效
perror("bind error");
exit(-1);
}
//监听:将主动连接变成被动连接,即:设置为只能等待被其他设备连接,而不能主动的去连接其他设备,这就是服务器端。
if(listen(sockfd,30)){ // 30表示最大只允许连接30个设备
perror("listen error");
exit(-1);
}
//客户端的IP地址与PORT信息,用client变量来存储
struct sockaddr_in client;
int len = sizeof(client);
int fd;
int m=20;
pthread_t thread;
while(1){
//等待客户连接
fd = accept(sockfd,(struct sockaddr *)&client,&len); /*当客户端与该服务端连接好后,将客户端的IP地址与PORT信息传给client变量来存储(由&client我们可以看得出来,该函数会使用解引用*,来改变main中client变量的值)。注意:每次连接成功都会产生一个新的文件描述符fd*/
if(fd<0){
if(!(m--)){ //m = 20,即:某个客户被允许连接失败次数为20次,如果20次还没有连接成功,则打印"accept error"
perror("accept error");
}
}else{
m=20;
/*开线程:注意:thread是一个变量,而不是一个线程的名字。每次成功开一个线程后,都会产生一个新的thread值,(由&thread我们可以看得出来,该函数会使用解引用*,来改变main中thread变量的值),所以,每当客户连接成功后,thread变量的值就会变化,而不同的thread值对应不同的线程。所以,每次有客户连接成功后,就会开辟不同的线程,而不是共用一个线程*/
if(pthread_create(&thread,NULL,dosth,&fd)){ /*注意:每次开辟一个线程后,都会开辟一个独立的栈来执行dosth()函数。所以,不同的线程,它们的dosth()函数是各自在各自的栈中执行,互不干扰。由于函数是在栈中运行的,所以栈的大小决定了线程可以开多少*/
perror("pthread_create error");
}
//将线程设置为分离属性,当线程结束后,会自动自己释放资源空间
pthread_detach(thread);
}
}
return 0;
}
//线程函数
void *dosth(void *arg)
{
int fd = *(int *)arg;
char buf[20];
char buff[10]="牛逼";
//接受数据,转发数据
int ret;
while(1){
bzero(buf,sizeof(buf));
ret = recv(fd,buf,sizeof(buf),0); //接收客户发来的信息,将信息赋值给buf数组
if(ret<=0){
close(fd);
pthread_exit(NULL);
}else{
printf("%s\n",buf); //打印buf数组中的信息
send(fd,buff,strlen(buff),0);
}
}
}