网络编程 day3

TCP多进程并发服务器 

#include <stdio.h>
#include "/home/ubuntu/head.h"

#define IP "192.168.124.85"
#define PORT 8888

void handler(int sig)
{
	while(waitpid(-1,NULL,WNOHANG)>0);
}



int main(int argc, const char *argv[])
{
	//回收僵尸进程
	if(signal(17,handler) == SIG_ERR)
	{
		ERR_MSG("signal");
		return -1;
	}
	//创建流式套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("socket create success sfd=%d __%d__\n",sfd,__LINE__);

	//允许端口快速被复用---监测端口号是否真的有进程在占用,如果没有,则快速复用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速复用成功\n");

	//定义并填充地址信息结构体,给服务绑定使用
	//真实的地址信息结构体根据地址族指定
	struct sockaddr_in sin;
	sin.sin_family   = AF_INET;
	sin.sin_port     = htons(PORT);
	sin.sin_addr.s_addr =inet_addr(IP);

	//绑定服务器自身的地址信息
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("binf");
		return -1;
	}
	printf("bind success __%d__\n",__LINE__);
	//讲套接字设置为被动接听状态
	if(listen(sfd,128)<0)
	{
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success __%d__\n",__LINE__);

	struct sockaddr_in cin;
	socklen_t addrlen = sizeof(cin);

	while(1)
	{
		//获取连接成功的客户端信息,生成一个新的套接字
		int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
		if(newfd<0)
		{
			ERR_MSG("accept");
			return -1;
		}

		printf("newfd=%d 客服端连接成功 __%d__\n",newfd,__LINE__);
		//创建父子进程
		pid_t cpid = fork();
		if(cpid<0)
		{
			ERR_MSG("recv");
			return -1;
		}
		else if(0 == cpid)
		{
			char buf[128]="";
			ssize_t res;
			while(1)
			{
				//接受客服端数据
				res = recv(newfd,buf,sizeof(buf),0);
				if(res<0)
				{
					ERR_MSG("recv");
					return -1;
				}
				else if(0 == res)
				{
					printf("[%s : %d]newfd=%d 客服端下线 __%d__\n",\
							inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
					break;
				}
				printf("[%s : %d]newfd=%d : %s __%d__\n",\
						inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
				//向客户端发送数据
				strcat(buf,"^_^");
				if(send(newfd,buf,sizeof(buf),0)<0)
				{
					ERR_MSG("send");
					return -1;
				}
				printf("send success __%d__\n",__LINE__);
			}

			exit(0);
		}
		//父进程
		close(newfd);
	}
	return 0;
}

 TCP多线程并发服务器

#include <stdio.h>
#include "/home/ubuntu/head.h"

#define IP "192.168.124.85"
#define PORT 8888

struct climsg
{
	int newfd;
	struct sockaddr_in cin;
};

void* deal_cli_msg(void* arg);

int main(int argc, const char *argv[])
{
	//创建流式套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("socket create success sfd=%d __%d__\n",sfd,__LINE__);

	//允许端口快速被复用---监测端口号是否真的有进程在占用,如果没有,则快速复用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速复用成功\n");

	//定义并填充地址信息结构体,给服务绑定使用
	//真实的地址信息结构体根据地址族指定
	struct sockaddr_in sin;
	sin.sin_family   = AF_INET;
	sin.sin_port     = htons(PORT);
	sin.sin_addr.s_addr =inet_addr(IP);

	//绑定服务器自身的地址信息
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("binf");
		return -1;
	}
	printf("bind success __%d__\n",__LINE__);
	//讲套接字设置为被动接听状态
	if(listen(sfd,128)<0)
	{
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success __%d__\n",__LINE__);

	struct sockaddr_in cin;
	socklen_t addrlen = sizeof(cin);
	pthread_t tid;
	struct climsg info;

	while(1)
	{
		info.newfd = accept(sfd, (struct sockaddr*)&info.cin, &addrlen);
		if(info.newfd < 0)
		{
			ERR_MSG("accept");
			return -1;
		}

		if(pthread_create(&tid,NULL,deal_cli_msg,(void*)&info)!=0)
		{
			fprintf(stderr,"pthread_create _%d_\n", __LINE__);
			return -1;
		}
		pthread_detach(tid);
	}

	//关闭
	if(close(sfd) < 0)
	{
		ERR_MSG("close");
		return -1;
	}
	return 0;
}

void* deal_cli_msg(void* arg)   //void* arg = &info
{
    int newfd = ((struct climsg*)arg)->newfd;
    struct sockaddr_in cin = ((struct climsg*)arg)->cin;

    char buf[128] = ""; 
    ssize_t res = 0;
    while(1)
    {   
        bzero(buf, sizeof(buf));
        //接收客户端数据
        res = recv(newfd, buf, sizeof(buf), 0); 
        if(res < 0)
        {
            ERR_MSG("recv");
            break;
        }
        else if(0 == res)
        {
            printf("[%s : %d] newfd=%d 客户端下线 __%d__\n", \
                    inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);
            break;
        }
        printf("[%s : %d] newfd=%d : %s __%d__\n", \
                inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf, __LINE__);

        //向客户端发送数据---->//从终端获取数据
        strcat(buf, "^_^");
        if(send(newfd, buf, sizeof(buf), 0) < 0)
        {
            ERR_MSG("send");
            break;
        }
        printf("send success __%d__\n", __LINE__);
    }   
    close(newfd);
    printf("newfd = %d被关闭\n", newfd);
    pthread_exit(NULL);
}

        

 

相关推荐

  1. 网络编程 day3

    2023-12-28 23:26:02       34 阅读
  2. 网络编程day4

    2023-12-28 23:26:02       22 阅读
  3. day11【网络编程

    2023-12-28 23:26:02       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-28 23:26:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-28 23:26:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-28 23:26:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-28 23:26:02       20 阅读

热门阅读

  1. css中Link和@import之间有什么区别?

    2023-12-28 23:26:02       39 阅读
  2. CSS新手入门笔记整理:CSS3选择器表

    2023-12-28 23:26:02       38 阅读
  3. Day01-Vue

    2023-12-28 23:26:02       36 阅读
  4. LeetCode414. Third Maximum Number

    2023-12-28 23:26:02       37 阅读
  5. 关于与Flask配套的Jinja2的使用

    2023-12-28 23:26:02       38 阅读
  6. Flask 账号详情展示

    2023-12-28 23:26:02       40 阅读
  7. Jenkins的shared library相关

    2023-12-28 23:26:02       32 阅读
  8. C语言之结构体

    2023-12-28 23:26:02       29 阅读
  9. c++ day2

    2023-12-28 23:26:02       33 阅读
  10. MySQL中的SIGNAL语句

    2023-12-28 23:26:02       32 阅读
  11. 保龄球。。。。

    2023-12-28 23:26:02       44 阅读
  12. css设置图片左上角加文字

    2023-12-28 23:26:02       34 阅读