定义[宏]处理错误
声明:
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0);
调用:
ERR_EXIT("connect");
1.int socket(int domain, int type, int protocol);
参数:
domain:指定通信协议族
type:指定socket类型
SOCK_STREAM:流式套接字 TCP
SOCK_DGRAM:数据报套接字 UDP
SOCK_RAW:原始套接字
protocol:协议类型
返回值:成功返回非零,即套接字描述字
例:int sockfd=socket(AF_INET,SOCK_STREAM,0);
2.int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
[1]第二个参数struct sockaddr *my_addr获得?
答:通过struct sockaddr_in ----> struct sockaddr,转换而来
struct sockaddr_in svraddr; // man 7 ip --->struct sockaddr_in
svraddr.sin_family=AF_INET;
svraddr.sin_port=htons(8001); //htons,不使用htonl
svraddr.sin_addr.s_addr=INADDR_ANY;//svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
[2]bind如何使用?
答:bind的第二个参数,使用的时候,要进行强制转换
int ret=bind(sockfd,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));
if(ret<0){
perror("bind");
exit(1);
}
3.int listen(int s, int backlog);
参数backlog的含义:指定未完成连接队列的最大长度
如果一个连接请求到达时,未完成连接队列已满--->客户端的行为分别为:
[1]客户端将接收到错误ECONNREFUSED.
[2]如果下层协议支持重发,那么这个连接请求将被忽略,这样客户端在重试的时候就有成功的机会
例:
4.int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
例:
struct sockaddr_in peeraddr; //对方的地址信息
socklen_t peerlen;
int newconn;
if((newconn=accept(sockfd,(struct sockaddr*)&peeraddr,&peerlen))<0){
perror("accept");
exit(1);
}
printf("new connect:peeraddr=%s, port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); //打印对方的地址信息
5.int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
例:
struct sockaddr_in svraddr;
svraddr.sin_family=AF_INET;
svraddr.sin_port=htons(8001);
svraddr.sin_addr.s_addr=inet_addr("127.0.0.1"); //svraddr.sin_addr.s_addr=INADDR_ANY;
int ret=connect(clisock,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));
6.setsockopt 设置套接字sockfd(文件描述字),可以地址复用
int optval=1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)); //设置地址复用
客户端服务器回射模型
客户端从键盘上获取数据,发送给服务器
服务器接收到客户端发送来的数据后,在屏幕上打印输出
服务器将接收到的数据,原样回射给客户端
客户端接收到服务器回射来的数据后,在屏幕上打印输出
客户端代码
int main(){
int clisock=socket(AF_INET,SOCK_STREAM,0);
if(clisock==-1){
perror("socket");
exit(1);
}
//服务器端的地址:svraddr
struct sockaddr_in svraddr;
svraddr.sin_family=AF_INET;
svraddr.sin_port=htons(8001);
//svraddr.sin_addr.s_addr=INADDR_ANY;
svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//connect:连接服务器端的地址avraddr
int ret=connect(clisock,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));
if(ret<0){
perror("connect");
exit(1);
}
printf("svraddr=%s,port=%d",inet_ntoa(svraddr.sin_addr),ntohs(svraddr.sin_port));
if(ret==-1){
perror("connect");
exit(1);
}
char sendbuf[1024];
char recvbuf[1024];
printf("\nsendbuf=");
while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL){ //从键盘上获取数据
write(clisock,sendbuf,strlen(sendbuf)); //向服务器发送数据
int ret=read(clisock,recvbuf,sizeof(recvbuf)); //读取服务器发来的数据
if(ret>0){
printf(" recvbuf=%s",recvbuf); //fputs(recvbuf,stdout);
printf("sendbuf=");
}
else if(ret==0){ //当read返回0时,证明对方关闭了socket连接
printf("peer alreadly close");
close(clisock);
break;
}
else if(ret<0){
perror("read fail");
exit(1);
}
memset(sendbuf,0,sizeof(sendbuf));
memset(recvbuf,0,sizeof(recvbuf));
}
return 0;
}
服务器代码
int main(){
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1){
perror("socket");
exit(1);
}
struct sockaddr_in svraddr; //man 7 ip --->struct sockaddr_in
svraddr.sin_family=AF_INET;
svraddr.sin_port=htons(8001);//host-->net
//svraddr.sin_addr.s_addr=INADDR_ANY;
svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
int optval=1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)); //设置地址复用
int ret;
ret=bind(sockfd,(struct sockaddr*)&svraddr,sizeof(struct sockaddr)); //bind
if(ret<0){
perror("bind");
exit(1);
}
printf("bind...\n");
if(listen(sockfd,5)<0){ //listen
perror("listen");
exit(1);
}
printf("listen...\n");
struct sockaddr_in peeraddr;
socklen_t peerlen;
int newconn;
if((newconn=accept(sockfd,(struct sockaddr*)&peeraddr,&peerlen))<0){ //accept
perror("accept");
exit(1);
}
printf("new connect:peeraddr=%s, port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
char recvbuf[1024];
while(1){
int ret=read(newconn,recvbuf,sizeof(recvbuf)); //读取client发送来的数据
if(ret>0){
printf("recvbuf = %;",recvbuf);
write(newconn,recvbuf,ret); //将读取的数据,回射给client
}
else if(ret==0){ //read 0 byte--->peer close
printf("peer already close\n");
close(newconn);
break;
//exit(0);
}
else if(ret<0){
printf("read data fail\n");
exit(0);
}
memset(recvbuf,0,sizeof(recvbuf));
}
return 0;
}