经过一段时间,总结下简单练习 tcp 、 udp 通信
tcp 传输层协议通信
//tcp 协议实现 server client端的传输层信息通信
//server = socket描述符 bind绑定ip+端口号 listen打开端口 accpet阻塞等待client连接
//client = socket描述符 connect连接serverip+端口号
//server client 使用send recv 通信
//tcp 通信 server端while不断开 client能不断连接
#include "func.h"
int main(int argc,char* argv[])
{
int sfd;
sfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
ret=bind(sfd,(struct sockaddr*)&ser,sizeof(ser));
listen(sfd,10); //端口就打开了
int new_fd=-1;
struct sockaddr_in cli;
int len=sizeof(cli);
char buf[128]={0};
fd_set rdset;
fd_set tmpset; //客户端交互new_fd socket 记录被监控的描述符
FD_ZERO(&tmpset);
FD_SET(0,&tmpset); //监控stdin、sfd 两个描述符
FD_SET(sfd,&tmpset);
while(1){
FD_ZERO(&rdset);
//第一次进入while循环时,只会进入sfd,&redset判断内部
memcpy(&rdset,&tmpset,sizeof(fd_set));
ret=select(11,&rdset,NULL,NULL,NULL);
if(FD_ISSET(sfd,&rdset)){
new_fd=accept(sfd,(struct sockaddr*)&cli,&len);
FD_SET(new_fd,&tmpset);
printf("client addr=%s,client port=%d\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
}
if(FD_ISSET(new_fd,&rdset)){ //第一次 new_fd不在rdset中
memset(buf,0,sizeof(buf));
ret=recv(new_fd,buf,sizeof(buf),0); //recv会阻塞
if(ret>0){
printf("client:%s\n",buf);
}else if(ret==0){
printf("bye bye\n");
close(new_fd);
FD_CLR(new_fd,&tmpset);
}
}
if(FD_ISSET(0,&rdset)&&FD_ISSET(new_fd,&tmpset)){ //new_fd不存在时会崩溃
memset(buf,0,sizeof(buf));
ret=read(0,buf,sizeof(buf));
if(ret>0){
send(new_fd,buf,strlen(buf)-1,0);
}else{
printf("bye bye\n");
break;
}
}
}
close(new_fd);
close(sfd);
return 0;
}
//client端
#include "func.h"
int main(int argc,char* argv[])
{
int sfd;
sfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
ret=connect(sfd,(struct sockaddr*)&ser,sizeof(ser));
char buf[128]={0};
fd_set rdset;
while(1)
{
FD_ZERO(&rdset);
FD_SET(0,&rdset);
FD_SET(sfd,&rdset);
ret=select(sfd+1,&rdset,NULL,NULL,NULL);
if(ret>0)
{
if(FD_ISSET(sfd,&rdset))
{
memset(buf,0,sizeof(buf));
ret=recv(sfd,buf,sizeof(buf),0);//recv会阻塞
if(ret>0)
{
printf("server:%s\n",buf);
}else if(0==ret)
{
printf("byebye\n");
break;
}
}
if(FD_ISSET(0,&rdset))
{
memset(buf,0,sizeof(buf));
ret=read(0,buf,sizeof(buf));
if(ret>0)
{
ret=send(sfd,buf,strlen(buf)-1,0);
printf("send ok\n");
}else{
printf("byebye\n");
break;
}
}
}
}
return 0;
}
udp 传输层协议通信
//udp通信 select模型
//server只能先recivefrom client
//server端
#include "func.h"
int main(int argc,char **argv){
int sfd;
sfd=socket(AF_INET,SOCK_DGRAM,0);
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
ret=bind(sfd,(struct sockaddr*)&ser,sizeof(ser)); //绑定端口 sfd+sockaddr_in
char buf[128]={0};
struct sockaddr_in cli;
memset(&cli,0,sizeof(cli));
int len=sizeof(cli);
//server只能先recvfrom 得到数据包;保存client socket
ret=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cli,&len);
printf("client addr=%s,client port=%d\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
fd_set rdset;
while(1){
FD_ZERO(&rdset);
FD_SET(0,&rdset);
FD_SET(sfd,&rdset);
ret=select(10,&rdset,NULL,NULL,NULL);
if(FD_ISSET(sfd,&rdset)){
memset(buf,0,sizeof(buf));
ret=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cli,&len);
if(ret>0){
printf("client: %s\n",buf);
// printf("client addr=%s,client port=%d\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
}else if(ret==0){
printf("bye bye\n");
}
}
if(FD_ISSET(0,&rdset)){
memset(buf,0,sizeof(buf));
read(0,buf,sizeof(buf)); //发送到client
sendto(sfd,buf,strlen(buf)-1,0,(struct sockaddr*)&cli,len);
}
//close(sfd); //应该永运不会改变
}
return 0;
}
//client端
#include "func.h"
int main(int argc,char* argv[])
{
int sfd;
sfd=socket(AF_INET,SOCK_DGRAM,0);
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
int len=sizeof(ser);
//客户端先发送
ret=sendto(sfd,"connect",10,0,(struct sockaddr*)&ser,len);
char buf[128]={0};
struct sockaddr_in cli; //用来保存recvfrom传出参数
memset(&cli,0,sizeof(cli));
fd_set rdset;
while(1){
FD_ZERO(&rdset);
FD_SET(0,&rdset);
FD_SET(sfd,&rdset);
ret=select(sfd+1,&rdset,NULL,NULL,NULL);
if(FD_ISSET(sfd,&rdset)){
memset(buf,0,sizeof(buf));
recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cli,&len);
printf("server: %s\n",buf);
}
if(FD_ISSET(0,&rdset)){
memset(buf,0,sizeof(buf));
read(0,buf,sizeof(buf)); //发送至server
sendto(sfd,buf,strlen(buf)-1,0,(struct sockaddr*)&ser,len);
}
}
close(sfd);
return 0;
}