ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux C实现简单,多进程,多线程服务器

2021-05-26 23:03:43  阅读:104  来源: 互联网

标签:include addr int svraddr ret Linux sockfd 服务器 多线程


简单服务器

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>

int main(){
    // 创建服务端fd
    int listenfd = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
    if(listenfd < 0){
        printf("socket error");
        return -1;
    }

    // 创建IP地址
    struct sockaddr_in svraddr;/*声明一个变量,类型为协议地址类型*/
    svraddr.sin_family = AF_INET;/*使用IPv4协议*/
    svraddr.sin_port = htons(8887);/*监听8887端口*/
    svraddr.sin_addr.s_addr = htonl(INADDR_ANY);/*绑定本机IP,使用宏定义绑定*/

    // 服务端fd和ip地址绑定
    if(bind(listenfd ,(struct sockaddr *)&svraddr,sizeof(svraddr)) < 0){
        printf("bind error");
        return -1;
    }

    // 上面创建和客户端一样,closed状态,当调用listen后从closed状态转listen
    if(listen(listenfd, 20) < 0){
        printf("listen error");
        return -1;
    }

    // 下面是客户端socket
    struct sockaddr_in cliaddr;/*只是声明,并没有赋值*/
    memset(&cliaddr, 0, sizeof(cliaddr));
    socklen_t ret = sizeof(cliaddr);
    // accept会阻塞进程
    // 客户端生成的fd,通过给客户端fd写入内容就会发送到客户端
    int sockfd= accept(listenfd, (struct sockaddr*)&cliaddr, &ret);
    if(sockfd < 0){
        printf("appect error");
        return -1;
    }

    char str[] = "Hello World";
    write(sockfd , str, sizeof(str));

    close(sockfd);
    close(listenfd);
}

客户端代码

#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main()
{
    int sockfd= socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

    if(sockfd== -1){
        printf("socket error");
        return -1;
    }

    struct sockaddr_in svraddr;
    svraddr.sin_family = AF_INET;/*使用IPv4协议*/
    svraddr.sin_port = htons(8887);/*需要连接的远程服务器端口*/
    svraddr.sin_addr.s_addr = inet_addr("127.0.0.1");/*需要连接的远程服务器IP*/

    if(connect(sockfd, (struct sockaddr *)&svraddr, sizeof(servaddr))  < 0){
        printf("connect error");
        return -1;
    }

    char str[64];
    read(sockfd, str, 64);
    printf(str);

    close(sockfd);
}

多进程服务器

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>

void doit(int sockfd);

int main()
{
    int listenfd= socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
    pid_t pid;

    if(listenfd < 0){
        printf("socket error");
        return -1;
    }

    struct sockaddr_in svraddr;/*声明一个变量,类型为协议地址类型*/
    svraddr.sin_family = AF_INET;/*使用IPv4协议*/
    svraddr.sin_port = htons(8887);/*监听8887端口*/
    svraddr.sin_addr.s_addr = htonl(INADDR_ANY);/*绑定本机IP,使用宏定义绑定*/

    if(bind(listenfd,(struct sockaddr *)&svraddr,sizeof(svraddr)) < 0){
        printf("bind error");
        return -1;
    }

    if(listen(listenfd, 20) < 0){
        printf("listen error");
        return -1;
    }

    for( ; ; ){   /*while(1){} */
        struct sockaddr_in cliaddr;/*只是声明,并没有赋值*/
        socklen_t cliaddr_size = sizeof(cliaddr);
        int sockfd= accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddr_size );

        if(sockfd < 0){
            printf("appect error");
            return -1;
        }

        if( (pid = fork()) == 0 ){
            close(listenfd);/*子进程不需要监听,关闭*/
            doit(sockfd);/*针对已连接的客户端套接字进行读写*/
            close(sockfd);/*处理完毕,关闭客户端连接*/
            exit(0);/*自觉退出*/
        }

        close(sockfd);
        /*close(listenfd);*/
    }
}

void doit(int sockfd){
    char str[] = "Hello World";
    sleep(3);//3秒之后再向客户端发送数据
    write(sockfd, str, sizeof(str));
}

多线程服务

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#define IP "192.168.102.175"
#define PORT 7000

void print_err(char *str, int line, int err_no) {
	printf("%d, %s :%s\n",line,str,strerror(err_no));
	_exit(-1);
}

/*子线程中先接收从客户端发来的消息,再发送一个消息给客户端*/
void *receive(void *pth_arg) {
	int ret = 0;
	long cfd = (long)pth_arg;
	char buf[100] = {0};
	while(1) {
		bzero(&buf, sizeof(buf));
		ret = recv(cfd, &buf, sizeof(buf),0);	
		if (-1 == ret) {
			print_err("recv failed",__LINE__,errno);
		}
		else if (ret > 0)
			printf("recv from client %s \n",buf);
		ret = send(cfd,"recv ok\n", sizeof("recv ok\n"), 0);
		if (-1 == ret) print_err("send failed", __LINE__, errno);
	}
}

int main()
{
	int skfd = -1, ret = -1;
	skfd = socket(AF_INET, SOCK_STREAM, 0);
	if ( -1 == skfd) {
		print_err("socket failed",__LINE__,errno);
	}

	struct sockaddr_in addr;
	addr.sin_family = AF_INET; //设置tcp协议族
	addr.sin_port = htons(PORT); //设置端口号
	addr.sin_addr.s_addr = inet_addr(IP); //设置ip地址

	ret = bind(skfd, (struct sockaddr*)&addr, sizeof(addr));
	if ( -1 == ret) {
		print_err("bind failed",__LINE__,errno);
	}
 
	ret = listen(skfd, 3);
	if ( -1 == ret ) {
		print_err("listen failed", __LINE__, errno);
	}
	
	//使用accept阻塞形式得监听客户端的发来的连接,并返回通信描述符
	long cfd = -1;
	pthread_t id;
	while (1) {
		struct sockaddr_in caddr = {0};
		int csize = sizeof(caddr);
		cfd = accept(skfd, (struct sockaddr*)&caddr, &csize);
		if (-1 == cfd) {
			print_err("accept failed", __LINE__, errno);
		}
		//建立连接后打印一下客户端的ip和端口号
		printf("cport = %d, caddr = %s\n", ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr));
	
		//使用accept返回到描述符,创建子线程进行数据传输
		int ret = pthread_create(&id,NULL,receive,(void*)cfd);
		if(-1 == ret) print_err("accept failed", __LINE__, errno); 
	}
	return 0;
}

标签:include,addr,int,svraddr,ret,Linux,sockfd,服务器,多线程
来源: https://www.cnblogs.com/x-mao/p/14815383.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有