socket

一、time服务器的客户端服务器,提交程序运行截图

dateclient.c
#include <stdio.h>
#include <netinet/in.h>                                                                   
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>

#define RIO_BUFSIZE 8192

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

#define MAXLINE 200

int main(int argc,char **argv){

    int clientfd,port;
    char *host,buf[MAXLINE];
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    rio_t rio;
    char str1[MAXLINE]="客户端IP:";
    char str2[MAXLINE]="服务器实现者学号:20201220";
    
    char str3[MAXLINE]="当地时间:";

    if(argc!=3){
    
        fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
        exit(0);
    }
    host = argv[1];
    port = atoi(argv[2]);

    clientfd = open_clientfd(host,port);
  
    while(1){
        

        recv(clientfd,rbuf,MAXLINE,0);

        printf("%s",str1);
        puts(host);

        printf("%s",str2);
        putchar('\n');

        printf("%s",str3);
      
        puts(rbuf);
       
        close(clientfd);
       
        exit(0);
    }

}
dateserver.c
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>                                                                   
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define MAXLINE 200
#define RIO_BUFSIZE 8192

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

typedef struct sockaddr SA;

typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;

void sigchld_handler(int sig){

    pid_t pid;
    int stat;

    while((pid = waitpid(-1,&stat,WNOHANG))>0){
        printf("child %d terminated\n",pid);
    }
    return;
}

int main(int argc,char **argv){

    int listenfd,connfd,port,clientlen;
    struct sockaddr_in clientaddr;
    struct hostent *hp;
    char *haddrp;
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    rio_t rio;
    time_t lt;
    tm *local;
    char str1[MAXLINE]="客户端IP:";
    char str2[MAXLINE]="服务器实现者学号:";
    char str3[MAXLINE]="当地时间:";


    if(argc != 2){
    
        fprintf(stderr,"usage:%s <port>\n",argv[0]);
        exit(0);
    }

    port = atoi(argv[1]);

    signal(SIGCHLD,sigchld_handler);
    listenfd = open_listenfd(port);
    while(1){
    
        clientlen = sizeof(clientaddr);
        connfd = accept(listenfd,(SA *)&clientaddr,&clientlen);

        hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
                sizeof(clientaddr.sin_addr.s_addr),AF_INET);
        haddrp = inet_ntoa(clientaddr.sin_addr);
        printf("server connected to %s (%s)\n",hp->h_name,haddrp);

        if(fork() == 0){
        close(listenfd);
        lt = time(NULL); 
        local = localtime(&lt);
        strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
        send(connfd,sbuf,MAXLINE,0);
        close(connfd);
        exit(0);
        }

        close(connfd);
    }
}

timeclient.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAXBUF 256

int main(int argc, char const *argv[])
{
	int s = 0;
	int n = 0;
	int reuse = 1;
	int port = 1220;
	struct sockaddr_in srv;
	char buf[MAXBUF] = {0};
	/*解析参数*/
	if (argc != 2)
	{
		printf("Usage:%s ServerIP\n", argv[0]);
		return -1;
	}
 
	bzero(&srv, sizeof(srv));
	srv.sin_family = PF_INET;
	srv.sin_addr.s_addr = inet_addr(argv[1]);
	srv.sin_port = htons(port);
	/*创建 UDP 套节字*/
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if(s<0){
		perror("socket");
		return -1;
	}
 
	while(1){
		sleep(1);
		time_t t=time(NULL);
		strcpy(buf,ctime(&t));
 		
		/*通过套节字 s 向服务器发送数据*/
		if ((n = sendto(s, buf, strlen(buf), 0, (struct sockaddr *) &srv, sizeof(struct sockaddr))) < 0)
		{
			perror("sendto");
			return -1;
		}else{
			printf("time is %s\n", buf);
		}
	}
}
timeserver.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
 
#define MAXBUF 256
int main(int argc, char const *argv[])
{
	int s = 0;
	int n = 0;
	int reuse = 1;
	int cli_len = sizeof(struct sockaddr);
	int port = 1220;
	char buf[MAXBUF] = {0};
	struct sockaddr_in addr, cli;
 
	/*初始化本地监听端口信息*/
	bzero(&addr, sizeof(addr));
	addr.sin_family = PF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(port);
 
	/*创建UDP套节字*/
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s<0)
	{
		perror("socket");
		return -1;
	}
 
	/*允许端口复用*/
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
 
	/*绑定指定端口*/
	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		perror("bind");
		return -1;
	}
 
	while(1){
		memset(buf, 0, MAXBUF);
		/*从套节字s中读取数据*/
		n = recvfrom(s, buf, MAXBUF, 0, (struct sockaddr *)&cli, &cli_len);
		if(n<0){
			perror("recvfrom");
			return -1;
		}else{
			printf("20201220--->time:",getpid());
			printf(" %s\n", buf);
		}
	}
	
	return 0;
}

二、echo服务器的客户端服务器,提交程序运行截图,服务器把客户端传进来的内容加入“服务器进程pid 你的学号 姓名 echo :”返回给客户端

echoclient.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#define MAX 256

char *SERVER_HOST = "127.0.0.1";
int sock, count;
struct sockaddr_in server_addr;
int client_init(char* SERVER_PORT)
{
    printf("客户端初始化\n");
    printf("创建套接字\n");
    sock = socket(AF_INET, SOCK_STREAM,0);
    printf("填充套接字\n");
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVER_HOST);
    server_addr.sin_port = htons(atoi(SERVER_PORT));

    printf("连接中.......\n");
    count = connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if(count < 0)
    {
        printf("连接失败\n");
        exit(3);
    }
    printf("连接成功\n");
    printf("初始化完成\n");
}

int main(int argc, char *argv[])
{
    int n;
    if(argc != 2)
    {
        fprintf(stderr,"%s\n","usage: port");
        exit(0);
    }
    char line[MAX], ans[MAX];
    client_init(argv[1]);
    printf("开始会话\n");
    while(1)
    {
        bzero(line, MAX);
        fgets(line,MAX,stdin);
        line[strlen(line)-1] = 0;
        write(sock, line, MAX);
        if(0 == strcmp("q",line))
            {
                printf("结束会话\n");
                close(sock);
                return 0;
            }
        read(sock, ans, MAX);
        printf("%s\n",ans);
    }
}

echoserver.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#define MAX 256
struct sockaddr_in server_addr, client_addr;
int mysock, csock;
int count, len;
void server_init(char* SERVER_PORT)
{
    printf("初始化TCP服务器\n");
    printf("创建TCP套接字\n");
    mysock = socket(AF_INET, SOCK_STREAM, 0);
    if(mysock < 0)
    {
        printf("调用套接字失败\n");
        exit(1);
    }
    printf("填充套接字\n");
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(atoi(SERVER_PORT));
    printf("绑定socket\n");
    count = bind(mysock,(struct sockaddr*)&server_addr, sizeof(server_addr));
    if(count < 0)
    {
        printf("绑定套接字失败\n");
        exit(3);
    }
    printf("开始监听\n");
    listen(mysock,5);
    printf("初始化结束\n");

}
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        fprintf(stderr,"%s\n","usage: port");
        exit(0);
    }
    server_init(argv[1]);
	printf("等待客户端连接...\n");

	while(1)
	{
		struct sockaddr_in  ;
		len = sizeof(client_addr);
		int csock = accept(mysock,(struct sockaddr*)&client_addr,&len);
		if(csock < 0)
		{
			perror("accept");
			continue;
		}
		pid_t pid = fork();
		if(pid < 0){
                perror( "fork");
                exit(1);
		}
		else if(pid == 0)
		{
		    pid_t pid_s = getpid();
		    pid_t pid_f = getppid();
			char buf[MAX], ans[MAX];
            close(mysock);
			while(1)
            {
			    memset(buf, 0 ,MAX);
			    memset(ans, 0 ,MAX);
			    printf("========connect [ip:port] = [%s:%d]========\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
			    read(csock,buf,MAX);
			    if(0 == strcmp("q",buf))
				{
				    printf("客户端pid:%d 关闭, 服务器监听中\n",pid_s);
					close(csock);
					return 0;
				}
			    sprintf(ans,"服务器父进程id:%d 当前进程id:%d ",pid_f,pid_s);
			    strcat(ans,"20201220CDJ 内容:");
			    strcat(ans,buf);
                count = write(csock,ans,MAX);
                printf("echo:%s\nwrote:%dbytes\npid:%d\n",ans,count,pid_s);
			}
		}
		else if(pid > 0)
        {
            close(csock);
        }
	}
}

三、服务器部署到华为云服务器,客户端用Ubuntu虚拟机。

四、用多线程或者多进程实现,至少连接两个客户端。

client.c
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
 //20201220
int main()
{
	int sockfd = socket(PF_INET,SOCK_STREAM,0);
	assert(-1!=sockfd);
 
	struct sockaddr_in ser,cli;
	memset(&ser,0,sizeof(ser));
	ser.sin_family=AF_INET;
	ser.sin_port=htons(6000);
	ser.sin_addr.s_addr=inet_addr("127.0.0.1");
	int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
	//assert(-1!=res);
 
	while(1)
	{
		printf("Please input:");
		fflush(stdout);
		char buff[128]={0};
		fgets(buff,127,stdin);
		buff[strlen(buff)-1]=0;
 
		if(strncmp(buff,"end",3)==0)
		{
		    break;
		}
		send(sockfd,buff,strlen(buff),0);
 
		memset(buff,0,sizeof(buff));
		recv(sockfd,buff,127,0);
		printf("%s\n",buff);
	}
	close(sockfd);
}
server.c
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<pthread.h>
 //20201220
void* communication(void* arg);
 
int main()
{
	int sockfd=socket(PF_INET,SOCK_STREAM,0);
	assert(-1!=sockfd);
 
	struct sockaddr_in ser,cli;
	ser.sin_family=AF_INET;
	ser.sin_port=htons(6000);
	ser.sin_addr.s_addr=inet_addr("127.0.0.1");
	int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
	assert(-1!=res);
 
	listen(sockfd,5);
 
	while(1)//保证服务器可以连接多个客户端
	{
		int len=sizeof(cli);
		int c=accept(sockfd,(struct sockaddr*)&cli,&len);
        if(c<0)
        {
            printf("link error\n");
            continue;
        }
 
		pthread_t id;
		int n=pthread_create(&id,NULL,communication,(void*)c);//创建线程,将文件描述符强转为void*,此处只能是值传递,地址传递的话,可能函数线程还没拿到该地址的值,就被主线程更改
		assert(n==0);
	}
    close(sockfd);
}
 
void* communication(void* arg)//函数线程完成与客户端的交互
{
	while(1)//实现与一个客户端的多次交互
	{
	    char buff[128]={0};
	    int c=(int)arg;//将文件描述符转回int型
	    int n=recv(c,buff,127,0);
	    if(n<=0)
	    {
			close(c);
			printf("%d client over\n",c);
			break;
	    }
	    printf("%d:%s\n",c,buff);
 
		send(c,"OK",2,0);
	}
}
posted @ 2022-11-08 22:49  acacacac  阅读(24)  评论(0编辑  收藏  举报