网络套接字编程 服务端-客户端(前面是代码,最后是运行结果)

本文是多进程编程,多线程请看(https://blog.csdn.net/xinger_28/article/details/94310088),在多线程编程一节详细介绍了网络套接字的编程流程。

//tcpsocket.h文件
#include<stdio.h>
#include<stdlib.h>
#include<error.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>

int Socket();
int Bind(int sockfd,const char*ip,uint16_t port);
int Listen(int sockfd);
int Connect(int sockfd,const char * ip,uint16_t port);
int Accept(int sockfd,char**ip,uint16_t*port);
int Recv(int newfd,char*buf,size_t len);
int Send(int newfd,char*buf,size_t len);
int Close(int fd);

 

//tcpsocket.c文件
#include"tcpsocket.h"
int Socket()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	return sockfd;
}

int Bind(int sockfd,const char*ip,uint16_t port)
{
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(port);
	addr.sin_addr.s_addr=inet_addr(ip);
	int len=sizeof(struct sockaddr_in);
	int ret=bind(sockfd,(struct sockaddr*)&addr,len);
	return ret;
}

int Listen(int sockfd)
{
	int ret=listen(sockfd,10);
	return ret;
}

int Connect(int sockfd,const char* ip,uint16_t  port)
{
	struct sockaddr_in addr;
	socklen_t len=sizeof(struct sockaddr_in);
	addr.sin_family=AF_INET;
	addr.sin_port=htons(port);
	addr.sin_addr.s_addr=inet_addr(ip);
	int ret=connect(sockfd,(struct sockaddr*)&addr,len);
	if(ret<0)
	{printf("connect error\n\n"); return -1;}
	printf("%d\n",ret);
	return ret;
}

int Accept(int sockfd,char**ip,uint16_t * port)
{
	struct sockaddr_in clic ;
	int len=sizeof(struct sockaddr_in);
	int newfd=accept(sockfd,(struct sockaddr*)&clic,&len);
	if(newfd<0)
	{
		return newfd;}
	*ip=inet_ntoa(clic.sin_addr);
	*port=ntohs(clic.sin_port);
	return newfd;
}

int Recv(int newfd,char*buf,size_t len)
{
	int ret=recv(newfd,buf,len,0);
	if(ret<0)
	printf("recv error\n");
	else if (ret==0)
	printf("connection shoutdown\n");
	return ret;
}

int Send(int newfd,char * buf,size_t len)
{
	int ret=send(newfd,buf,len,0);
	if(ret<0)
	printf("send error\n");
	else if (ret==0)
	printf("connection shoutdown\n");
	return ret;
}
int  Close(int fd)
{
	close(fd);
}
//thread_service.c文件
//服务端代码
#include"tcpsocket.h"

#include"tcpsocket.h"
//检查返回值是否正常
int  cheakRet(char*info,int ret)
{
	if(ret<0)

	{printf("%s\n",info);return -1;}
	return ret;
}
//针对某一客户端进行收发数据
int Recv_Send(int fd,char*clicip,uint16_t clicport)
{
	while(1){
	char buf[1024]={0};
	int ret=Recv(fd,buf,1023);	
	printf("connect : ip: %s  port: %d\n",clicip,clicport);
	printf("*   clic say:  %s \n",buf);
	if(ret<0)
	{printf("recv error\n");return -1;}
	else if(ret==0)
	{printf("connect is error\n");  
		return ret;}
	memset(buf,0x00,1024);
	printf("* send to :");
	scanf("%s",buf);
	printf("\n");
	ret=Send(fd,buf,strlen(buf));
	}
	return 0;
}
//创建孙子进程进行收发数据
void Accept_(int sockfd,char*clicip,uint16_t clicport)
{
	pid_t ret=fork();
	if(ret==0)
	{
	   pid_t gh=fork();
	    if(gh==0)
		Recv_Send(sockfd,clicip,clicport);
	   exit(0);
	}
	else if(ret>0)
	{close(sockfd);
	wait(ret);
	}
	else
	{printf("fork() error\n");
	}
}

int main()
{
	int sockfd=Socket();
	cheakRet("Socket error",sockfd);
	int ret=Bind(sockfd,"192.168.136.132",10000);
	cheakRet("Bind error",ret);
	ret=Listen(sockfd);
	cheakRet("Listen error",ret);
	while(1)
	{
	struct sockaddr_in clicaddr;
        socklen_t len=sizeof(struct sockaddr_in);
        char*clicip;
        uint16_t clicport;
        int newfd=Accept(sockfd,&clicip,&clicport);
	printf("connect : ip: %s  port: %d\n",clicip,clicport);
	Accept_(newfd,clicip,clicport);
	}	
	Close(sockfd);
	return 0;
}
//clic.c文件
//用于客户端连接请求
#include"tcpsocket.h"

int main()
{
	int sockfd=Socket();
	if(sockfd<0)
	{printf("sockfd error\n"); return -1;}
	int ret;
//注意此处不需要为套接字绑定地址信息,因为这份代码是客户端的
//如果绑定了地址信息,那么只能启动一个客户机,其他客户端在启动时,将会绑定失败,因为一个端口只能被一个进程绑定
//因此不需要绑定地址信息,操作系统将会根据此时的网络状况,计算机此时的网络帮我们绑定合适的地址
	int newfd=Connect(sockfd,"192.168.136.132",10000);
	if(newfd<0)
	{printf("connection error\n");return -1;}
	while(1){
	char buf[1024]={0};
	printf("send to : ");
	scanf("%s",buf);
	ret=Send(sockfd,buf,strlen(buf));
	if(ret<0)
	{printf("recv error\n");return -1;}
	else if(ret==0)
	{printf("connect ir error\n");return -1;}
	memset(buf ,0x00,1024);
	ret=Recv(sockfd,buf,1023);
	printf("service say:[%s]\n",buf);
	if(ret<0)
	{printf("Recv error\n");return -1;}
	else if(ret==0)
	{printf("quit\n");return -1;}
	}
	Close(sockfd);
	return 0;
}

实际操作截图:

1.进行编译:

gcc threads_service.c tcpsocket.c -o pthread_servi

 

gcc clic.c tcpsocket.c -o clicl

 

2.运行结果:(先启动服务端进行监听)

        

   服务端                                                        客户端1                                                        客户端2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值