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 @ 2022-10-13 09:27  starc的miao  阅读(253)  评论(0)    收藏  举报