#include<stdio.h>
#include<string.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<errno.h>
#include<arpa/inet.h>
#include<unistd.h>
//打印错误信息的宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__\n",__LINE__);\
perror(msg);\
}while(0)
//宏定义IP地址
#define IP "192.168.31.154"
//宏定义端口号pott
#define POTR 9999
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);//返回文件描述符
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
//填充信息结构体信息
struct sockaddr_in sock;
//主机端口字节序转网络端口字节序
sock.sin_port=htons(POTR);//返回值是网络端口字节序
//主机源地址IP转换成网络字节序IP地址
sock.sin_addr.s_addr=inet_addr(IP);//返回网络IP字节序
sock.sin_family =AF_INET;
//创建的这个结构体必须要IPV4地址类型
//绑定本机IP和端口号到bind,填充文件描述符
//这里完成后网络地址就绑定完成了
if(bind(sfd,(struct sockaddr*)&sock,sizeof(sock))<0)
{
perror("bind");
return -1;
}
//将套接字描述符放入listen,化为监听程序
//为实现查看是否存在消息队列元素生成而绑定
if(listen(sfd,5)<0)
{
perror("listen");
return -1;
}
printf("listen seting success\n");
//从已完成链接的队列列头中,取出一个客户端的信息
//创建一个新的套接字文件描述符
//再次创建一个结构体用来接收新的文件描述符对应数据
struct sockaddr_in cin;
socklen_t len =sizeof(cin);//生成一个socken_t类型的变量
//创建生成一个新的套接字文件描述符
int newfd=accept(sfd,(struct sockaddr*)&cin,&len);
if(newfd<0)
{
perror("accept");
return -1;
}
//网络字节序的IP-->点分十进制
//网络字节序的port-->本机字节序
printf("[%s:%d]newfd=%d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
char buf[128]="";
char buf1[128]="";
ssize_t res=0;
while(1)
{
bzero(buf,sizeof(buf));
bzero(buf1,sizeof(buf1));
//循环接收
res=recv(newfd,&buf,sizeof(buf),0);
if(res<0)
{
perror("recv");
return -1;
}
else if(res==0)
{
printf("[%s:%d]newfd=%d:%s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf);
break;
}
printf("[%s:%d]newfd=%d:%s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf);
fgets(buf1,sizeof(128),stdin);
buf1[strlen(buf1)-1]='\0';
send(newfd,&buf1,sizeof(buf1),0);
}
close(sfd);
close(newfd);
return 0;
}