TCP-server服务器代码

第一版

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> //close()
#include <string.h> //strcmp()等字符串操作函数
#include <stdlib.h> //atoi() 字符串转int
int main(int argc, char *argv[])
{
//判断命令行参数是否满足
if(argc != 2)
{
printf("请传递一个端口号\n");
return -1;
}
//将接收端口号并转换为int
int port = atoi(argv[1]);
if( port<1025 || port>65535 )//0~1024一般给系统使用,一共可以分配到65535
{
printf("端口号范围应为1025~65535");
return -1;
}
//1 创建tcp通信socket
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(socket_fd == -1)
{
perror("创建tcp通信socket失败!\n");
return -1;
}
//2 绑定socket地址
struct sockaddr_in server_addr = {0};//存放地址信息
server_addr.sin_family = AF_INET;//AF_INET->IPv4
server_addr.sin_port = htons(port);//端口号
server_addr.sin_addr.s_addr = INADDR_ANY;//让系统检测本地网卡,自动绑定本地IP
int ret = bind(socket_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) );
if(ret == -1)
{
perror("bind failed!\n");
return -1;
}
//3 设置监听队列,设置为可以接受5个客户端连接
ret = listen(socket_fd, 5);
if(ret == -1)
{
perror("listen falied!\n");
}
printf("server is running!\n");
struct sockaddr_in client_addr = {0};//用来存放客户端的地址信息
int len = sizeof(client_addr);
int new_socket_fd = -1;//存放与客户端的通信socket
//4 等待客户端连接
new_socket_fd = accept( socket_fd, (struct sockaddr *)&client_addr, &len);
if(new_socket_fd == -1)
{
perror("accpet error!\n");
}
else
{
printf("IP:%s, PORT:%d [connected]\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
//循环接收信息
while(1)
{
char buf[1024] = {0};
read(new_socket_fd, buf, sizeof(buf));//阻塞,,等待客户端发来消息
printf("receive msg:%s\n", buf);//打印消息
if(strcmp(buf, "exit") == 0)
{
break; //退出循环
}
}
//5 关闭socket
close(new_socket_fd);
close(socket_fd);
return 0;
}

第二版

/*
学习代码写法,需要实现的功能如下:
1.利用函数初始化和分配套接字给服务器。
2.利用config文件配置服务器参数。可以参考redis的源码。
3.编写Makefile脚本实现代码编译
4.编写CMake脚本实现代码编译
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int initServer(const struct sockaddr_in server_addr, int type, socklen_t size, int backlog);
int initAccept(int server_fd);
// 主函数
int main(int argc, char *argv[])
{
int type = SOCK_STREAM;
struct sockaddr_in server_addr = {0}; // <netinet/in.h>
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8001);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&(server_addr.sin_zero), 8);
socklen_t size = sizeof(server_addr);
int backlog = 5;
// 服务器初始化函数
/*
思考为什么不是引用传递???
如果是引用传递,bind() BUG:Address family not supported by protocol
--> AF_INET对应的是sockaddr_in
*/
int server_fd = initServer(server_addr, type, size, backlog);
int client_fd = initAccept(server_fd);
// 循环接收信息
while(1)
{
char buf[1024] = {0};
read(client_fd, buf, sizeof(buf));//阻塞,,等待客户端发来消息 // <unistd.h>
printf("receive from client msg:%s\n", buf);//打印消息
if(strcmp(buf, "q") == 0)
{
break; //退出循环
}
}
// 关闭socket套接字
close(client_fd); // <unistd.h>
close(server_fd);
exit(EXIT_SUCCESS);
}
int initAccept(int server_fd)
{
struct sockaddr_in client_addr = {0}; // 用来存放客户端的地址信息
int len = sizeof(client_addr); // socklen_t
int new_socket_fd = -1; // 存放与客户端的通信socket
// 等待客户端连接
new_socket_fd = accept(server_fd, (struct sockaddr *)&client_addr, &len);
if(new_socket_fd == -1)
{
perror("accpet error!\n");
}
else
{
// 注意网络子继续到主机字节序inet_ntoa() <arpa/inet.h>
printf("IP:%s, PORT:%d [connected]\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
return new_socket_fd;
}
// 初始化服务器的函数
int initServer(const struct sockaddr_in server_addr, int type, socklen_t size, int backlog)
{
int fd;
int err;
// 创建套接字
if ((fd = socket(server_addr.sin_family, type, 0)) < 0)
{
perror("Error initServer:");
exit(EXIT_FAILURE);
}
else
{
printf("Create socket Success.\n");
}
// 绑定端口和IP
/*
第二个参数需要强制类型转换(struct sockaddr *),还有取地址符&
第三个参数,可以sizeof(server_addr)或者sizeof(struct sockaddr)
*/
if (bind(fd, (struct sockaddr *) &server_addr, size) < 0)
{
perror("Error:");
exit(EXIT_FAILURE);
}
else
{
printf("Bind success.\n");
}
// 设置监听队列,设置为可以接受5个客户端连接
if (listen(fd, backlog) < 0)
{
perror("Error:");
exit(EXIT_FAILURE);
}
else
{
printf("Listen success.\n");
}
return fd;
}
posted @   steve的miao  阅读(238)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示