下面是服务端的程序代码,客户端连接成功后服务器将打印出客户端的地址信息,并将服务器本地的时间发送给客户端:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int sockfd;
void sig_handler(int signo)
{
if(signo == SIGINT)
{
printf("server close!
");
/*关闭socket*/
close(sockfd);
exit(1);
}
}
/*输出客户端连接的地址信息*/
void out_addr(struct sockaddr_in *clientaddr)
{
//将端口从网络字节序转换成主机字节序
int port = ntohs(clientaddr->sin_port);
char ip[16];
memset(ip, 0, sizeof(ip));
//将IP地址从网络字节序转换为点分十进制
inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip, sizeof(ip));
printf("client: %s(%d) connected
", ip, port);
}
//服务器发送数据给客户端
void do_service(int fd)
{
//获取系统时间
long t = time(0);
char *s = ctime(&t);
size_t size = strlen(s)*sizeof(char);
//将服务器端获取的系统时间写回到客户端
if(write(fd, s, size) != size)
{
perror("write error");
}
}
int main(int argc, char* argv[])
{
if(argc < 2)
{
printf("usage: %s #port
", argv[0]);
exit(1);
}
if(signal(SIGINT, sig_handler) == SIG_ERR)
{
perror("signal sigint error");
exit(1);
}
/*1.创建socket
* 注:socket创建在内核中,是一个结构体
* AF_INET:IPV4
* SOCK_STREAM:tcp协议
* */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket error");
exit(1);
}
/*2.将socket和地址(ip、port)进行绑定*/
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
//地址中填入ip、port、internet地质族类型
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[1]));//转换为网络字节序
serveraddr.sin_addr.s_addr = htons(INADDR_ANY);//响应所有的网卡请求
if(bind(sockfd, (struct sockaddr*)(&serveraddr), sizeof(serveraddr)) < 0)//注意地址要强制转换为通用地址
{
perror("bind error");
exit(1);
}
/*3.调用listen函数启动监听(指定的端口监听)
* 通知系统去接收来自客户端的连接请求
* (将接收到的客户端的请求放置到对应的队列中)
*第二个参数:指定队列的长度
* */
if(listen(sockfd, 10) < 0)
{
perror("listen error");
exit(1);
}
/*4.调用accept函数从队列中获取一
* 个客户端的请求连接,并返回一个新的socket描述符
* 第二个参数:用来获取客户端的地址信息,如果不需要传入NULL
* 注意:若没有客户端连接,调用此函数会阻塞。
* */
struct sockaddr_in clientaddr;
socklen_t clientaddr_len = sizeof(clientaddr);
while(1)
{
int fd = accept(sockfd, (struct sockaddr*)&clientaddr, &clientaddr_len);
if(fd < 0)
{
perror("accept error");
continue;
}
/*5.调用IO函数和连接的客户端进行双向的通信
* */
out_addr(&clientaddr);
do_service(fd);
/*6.关闭socket
* */
close(fd);
}
return 0;
}