目录
服务端
第一步socket
第二步struct sockaddr_in
第三步(可以与第二步合为一个步骤)bind
第四步listen
第五步accept
第六步recv
第七步close
详细代码
服务端
第一步socket
1.操作:创建流式套接字;
2.所用函数:socket(AF_INET,SOCK_STREAM,0);
3.函数参数:AF_INET代表所使用的网际协议版本;
SOCK_STREAM代表创建的是流式套接字;
0为自动匹配该项;
4.返回值:sockfd返回值小于0时,创建失败;
int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < -1)
{
perror("socket err");
return -1;
}
printf("socket sucess\n");
第二步struct sockaddr_in
1.操作:填充结构体;
2.结构体:struct sockaddr_in;
要填充的成员变量:sin_family为所使用的网际协议版本;
sin_port为端口号;sin_addr.s_addr为ip;
struct sockaddr_in serveraddr,clientaddr;
serveraddr.sin_family = AF_INET; //使用的是ipv4地址
//htons函数将主机字节序转换为网络字节序,atoi函数将字符串端口号转换为数字端口号
serveraddr.sin_port = htons(atoi(argv[1]));
serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");//32位的IP地址
第三步(可以与第二步合为一个步骤)bind
1.操作:绑定套接字;
2.所用函数:bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
3.函数参数:sockfd->套接字描述符;
(struct sockaddr *)&serveraddr->通用结构体指针类型的结构体;
sizeof(serveraddr)->结构体大小;
4.返回值:bind返回值小于0时,绑定失败;
if(bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0)
{
perror("bind error");
return -1;
}
printf("bind sucess\n");
第四步listen
1.操作:监听套接字,将主动套接字转化为被动套接字等待;
2.所用函数:listen(sockfd,6);
3.函数参数:sockfd->套接字描述符;
6->任意正整数;
4.返回值:listen返回值小于0时,监听失败;
if(listen(sockfd,6) < 0)
{
perror("listen err");
return -1;
}
printf("listen sucess\n");
第五步accept
1.操作:阻塞并等待客户端连接,接收客户端的连接请求;
2.所用函数:accept(sockfd,NULL,NULL);
或accept(sockfd,(struct sockaddr *)&clientaddr,&len);
3.函数参数:
sockfd->套接字描述符;
(struct sockaddr *)&clientaddr->客户端的ip和端口号结构体对象(和serveraddr一起定义);
len->clientaddr结构体的大小(由sizeof(clientaddr);计算得);
后两位参数如果不需要可以填NULL;
4.返回值:accept返回值小于0时,接收失败;成功时会返回用于通信的描述符;
socklen_t len = sizeof(clientaddr);
int acceptfd;
acceptfd = accept(sockfd,(struct sockaddr *)&clientaddr,&len);
if(acceptfd < 0)
{
perror("accept err");
return -1;
}
printf("accept sucess\n");
//打印接收到的客户端的ip与端口信息
printf("client:ip = %s,port = %d\n",inet_ntoa(clientaddr.sin_addr),\
ntohs(clientaddr.sin_port));
第六步recv
1.操作:接收并打印客户端的消息;
2.所用函数:recv(acceptfd,buf,sizeof(buf),0);
3.函数参数:acceptfd->用于通信的描述符;
buf->缓存接收消息的字符数组;
sizeof(buf)->计算数组大小;
0->接收阻塞;
最后一个参数填MSG_DONTWAIT时表示接收非阻塞;
4.返回值:recv返回值小于0时,表示接收失败,等于0时表示客户端退出;
int recvbytes = recv(acceptfd,buf,sizeof(buf),0);
if(recvbytes < 0)
{
perror("recv err");
return -1;
}else if(recvbytes == 0)
{
printf("client exit\n");
}else
{
printf("buf:%s\n",buf);
}
第七步close
1.操作:关闭描述符;
2.所用函数:close -- close(sockfd);close(acceptfd);
详细代码
/********
*服务器代码
*server.c
* 测试方式如下
* telnet "ip" "端口"
* telnet 192.168.50.16 8888
*********/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <wait.h>
int main(int argc, char const *argv[])
{
if (argc != 2)
{
printf("input %s <port>\n", argv[0]);
return -1;
}
//1.创建流式套接字 socket
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < -1)
{
perror("socket err");
return -1;
}
printf("socket sucess\n");
//2.绑定套接字,ip和端口,bind
//填充结构体
struct sockaddr_in serveraddr, clientaddr;
serveraddr.sin_family = AF_INET; //使用ipv4地址
serveraddr.sin_port = htons(atoi(argv[1])); //主机字节序到网络字节序
serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0"); //32位的IP地址
socklen_t len = sizeof(clientaddr);
//绑定套接字
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind error");
return -1;
}
printf("bind sucess\n");
//3.监听,将主动套接字转化为被动套接字等待
if (listen(sockfd, 6) < 0)
{
perror("listen err");
return -1;
}
printf("listen sucess\n");
//4.阻塞等待客户端连接,即接收客户端请求
while (1)
{
int acceptfd;
acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &len);
if (acceptfd < 0)
{
perror("accept err");
return -1;
}
printf("accept sucess\n");
printf("client:ip = %s,port = %d\n", inet_ntoa(clientaddr.sin_addr),
ntohs(clientaddr.sin_port));
//5.循环收发消息
int recvbytes;
char buf[128];
while (1)
{
recvbytes = recv(acceptfd, buf, sizeof(buf), 0);
if (recvbytes < 0)
{
perror("recv err");
return -1;
}
else if (recvbytes == 0)
{
printf("client exit\n");
break;
}
else
{
printf("buf:%s\n", buf);
}
}
//关闭
close(acceptfd);
close(sockfd);
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)