服务器
**************************************************************************************************************
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#define PTOR 6666
#define IP "192.168.31.162"
#define ERR_MSG(msg) do{
fprintf(stderr,"__%d__n",__LINE__);
perror(msg);
}while(0)
int main(int argc, const char *argv[])
{
//1、创建流式套接字,返回值为文件描述符
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//如果不加这段代码,则服务器异常退出后,会导致端口号在30s~3min内释放不出来
//当程序结束后,想要让其他进程能够快速复用端口号,就可以使用下面的代码
//允许端口快速被重用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse ,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速重用n");
//2、填充地址信息结构体,真实的地址信息结构体根据地址族制定
struct sockaddr_in sin;
sin.sin_family =AF_INET;//必须填AF_INET;
sin.sin_port =htons(PTOR);//网络字节序,端口号是2字节,所以用htons将主机字节序转为网络字节序
sin.sin_addr.s_addr =inet_addr(IP);//本机IP
//printf("%d:%d_,%#xn",__LINE__,htons(PTOR),inet_addr(IP));
//3、将地址信息结构体绑定到套接字上
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
//4、将套接字设置为被动监听状态
if(listen(sfd,128)<0)
{
ERR_MSG("listen");
return -1;
}
printf("服务器设置被动监听设置成功n");
struct sockaddr_in cin;
socklen_t cinlen=sizeof(cin);
//5、accept从队头获取一个客户端信息
int newfd = accept(sfd,(struct sockaddr *)&cin,&cinlen);
if(newfd<0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d] newfd = %d 连接成功n",
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd);
//6、数据传输
char buf[32]="";
ssize_t res=0;
while(1)
{
//接收
bzero(buf,sizeof(buf));
res=recv(newfd,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}
else if(0==res)
{
printf("newfd=%d 客户端关闭n",newfd);
break;
}
printf("res:%ld,newfd:%d,res:%sn",res,newfd,buf);
//发送
//将发送一个数据到用户IP
printf("服务器发送–>n");
fgets(buf,sizeof(buf),stdin);
buf[sizeof(buf)-1]=0;
if(send(newfd,buf,sizeof(buf),0)<0)
{
ERR_MSG("send");
return -1;
}
bzero(buf,sizeof(buf));
printf("send successn");
}
close(newfd);
close(sfd);
return 0;
}
**************************************************************************************************************
客户端
**************************************************************************************************************
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#define ser_PTOR 6666
#define ser_IP "192.168.31.162"
#define ERR_MSG(msg) do{
fprintf(stderr,"__%d__n",__LINE__);
perror(msg);
}while(0)
int main(int argc, const char *argv[])
{
//1、创建流式套接字,返回值为文件描述符
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//绑定客户端自身IP和端口,到对应的套接字上;——非必要绑定
//不绑定程序运行后操作系统会自动分配一个在49152—65535之间的端口号给套接字
//填充地址信息结构体,真实地址信息结构体根据地址族来制定
//struct sockaddr_in
//2、填充服务器的地址信息结构体,因为connect函数中要通过地址信息结构体来链接服务器
struct sockaddr_in sin;
sin.sin_family =AF_INET;//必须填AF_INET;
sin.sin_port =htons(ser_PTOR);//服务器绑定的端口
sin.sin_addr.s_addr =inet_addr(ser_IP);//服务器绑定的IP
//注意,切换网络环境后IP是会发生改变的
//3、连接服务器
if(connect(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("connect");
return -1;
}
printf("connect successn");
struct sockaddr_in cin;
socklen_t cinlen=sizeof(cin);
//6、数据传输
char buf[32]="";
ssize_t res=0;
while(1)
{
//发送
//将获取到的数据拼接后发送回去
printf("请输入–>n");
fgets(buf,sizeof(buf),stdin);
buf[sizeof(buf)-1]=0;
if(send(sfd,buf,sizeof(buf),0)<0)
{
ERR_MSG("send");
return -1;
}
bzero(buf,sizeof(buf));
printf("send successn");
//接收
bzero(buf,sizeof(buf));
res=recv(sfd,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}
else if(0==res)
{
printf("sfd=%d 客户端关闭n",sfd);
break;
}
printf("res:%ld,sfd:%d,res:%sn",res,sfd,buf);
}
close(sfd);
return 0;
}