0
点赞
收藏
分享

微信扫一扫

UNIX编程—网络socket

船长_Kevin 2022-03-12 阅读 91

1 前言

在进行网络socket编程之前,首先要明白计算机通信的原理。网络socket编程是建立在客户端和服务端之间的相互通信,这就必须要了解到计算机网络的知识。我所写的内容是实现简单的本机之间的相互通信。还可以上升到局域网之间不同pc的通信,甚至是不在同一局域网内的pc之间的相互通信。
 

2概念梳理
2.1  UNIX下文件I/O
写客户端和服务端程序时,你需要利用C语言的基本语法和UNIX下相关系统调用以及库函数。包括socket,connect,bind,listen,write,read的使用等等。
2.2 计算机网络
实现客户端和服务端通信,必须要弄清楚通信原理,包括TCP/UDP协议,IPV4/IPV6的理解等。对于本例客户端和服务端,他们分别占用着同一ip下不同的端口,所以在进行通信时,必须要弄清楚目的ip目的端口以及源ip源端口。我们需要指定连接服务端的端口,但是客户端的端口不用去指定,因为客户端可以有很多个,可以让linux操作系统内核随机分配,这样会大大减少内存的压力。
2.3 linux基本操作
执行操作时,我们必须要了解在linux命令行下的基本操作才能对我们的pc进行操控,比如gcc的调试和vim的基本使用,这都是非常有必要的。


3代码及运行结果

3.1 服务端程序

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
 
#define MSG "hello , I am accept\n"
 
void useage(char *progname)
{
        printf("%s useage:\n",progname);
        printf("-p(--port):specify server  listen port\n");
        printf("-h(--help):print this help information\n");
        return;
}
 
int main(int argc, char **argv)
{
 
        int                     sockfd = -1;
        int                     clifd = -1;
        int                     rv = -1;
        struct sockaddr_in      cliaddr;
        struct sockaddr_in      servaddr;
        socklen_t               len=1;
        int                     port=0;
        char                    buf[1024];
        struct option           opts[] = {
                {"port",required_argument,NULL,'p'},
                {"help",no_argument,NULL,'h'},
                {NULL,0,NULL,0}
        };
        int                     opt;
        int                     idx;
 
        while((opt = getopt_long(argc,argv,"p:h",opts,&idx)) != -1)
        {
                switch(opt)
                {
                        case 'p':
                                 port = atoi(optarg);
                                 break;
                        case 'h':
                                 useage(argv[0]);
                                 return -1;
                }
        }
 
        if(!port)
        {
                useage(argv[0]);
                return 0;
        }
 
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        if(sockfd < 0)
        {
                printf("Create socket failure:%s\n",strerror(errno));
                return -1;
        }
        printf("Create socket[%d] successfully\n",sockfd);
 
        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sin_family=AF_INET;
        servaddr.sin_port=htons(port);
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        rv = bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
        if(rv<0)
        {
                printf("socket[%d] bind on port[%d] failure:%s\n",sockfd,
                                port,strerror(errno));
                return -2;
        }
 
        listen(sockfd,13);
 
 
//        inet_aton(servip,&servaddr.sin_addr);
        printf("Connect client successfully:\n");
 
        while(1)
        {
                clifd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);
                if(clifd<0)
                {
                        printf("Accept new client faliure:%s\n",strerror(errno));
                        continue;
                }
                printf("Accept new client[%s:%d] successfully!\n",
                                inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
 
                memset(buf,0,sizeof(buf));
                rv = read(clifd,buf,sizeof(buf));
                if(rv < 0)
                {
                        printf("read failure:%s\n",strerror(errno));
                        close(clifd);
                        continue;
                }
                else if(rv == 0)
                {
                        printf("socket[%d] get disconnect\n",clifd);
                        close(clifd);
                        continue;
                }
                else if(rv > 0)
                {
                        printf("read %dbyte from client:%s\n",rv,buf);
                }
 
                rv = write(clifd,MSG,sizeof(MSG));
                if(rv < 0)
                {
                        printf("write failure:%s\n",strerror(errno));
                        close(clifd);
                        continue;
                }
                printf("close client socket[%d]\n",clifd);
                close(clifd);
 
        }
        close(sockfd);
 
}


3.1客户端程序(3种写法)

3.1.1 第一种方法---在程序内指定IP和端口

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

 #define MSG_STR "Hello i am zhangkang\n"//添加宏定义,方便write函数中strlen的使用

int main (int argc,char *argv[])
{
	int               sockfd=-1;
    int               rv=-1;
    struct sockaddr_in servaddr;//ipv4 结构体的定义;
    char              *servip="127.0.0.1";//与本机进行通信;	
    int               port=6666;//指定服务器端口 
    char              buf[1024];//指定读区
	
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if (socket<0)
	{
		printf("Creat socker faliure:%s\n",strerror(errno));
		return -1;
	}
	printf("Creat socket[%d] successful!\n",sockfd);
    
	memset(&servaddr,0,sizeof(servaddr));//将定义ipv4的结构体清空;
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(port);
	inet_aton(servip,&servaddr.sin_addr);//写入ipv4结构体中的一些数据;
	
    rv=connect(sockfd(struct sockaddr *)&servaddr,sizeof(servaddr));
	if(rv<0)
	{
	        printf("Connect to server[%s:%d] failure:%s\n",servip,port,strerror(errno));
		return -2;
	}

	printf("Connect to server[%s:%d] successful!",servip,port);
        
	while(1)
	{
	    rv=write(sockfd,MSG_STR,strlen(MSG_STR));
            if(rv<0)
            {
                   printf("Write to server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
	           break;
            }

	    memset(buf,0,sizeof(buf));//将buf清空;
	    rv=read(sockfd,buf,sizeof(buf));
	    if(rv<0)
	    {
	            printf("Read data from  server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
		    break;
	    }
	    else if(rv==0)
	    {
		    printf("Socket[%d] get disconnected\n",sockfd);
		    break;
	    }
	    else if(rv>0)
	    {
		    printf("Read %d bytes data from Server:%s\n",rv,buf);
	            break;
	    }

	}

        close(sockfd);

3.1.1.1 第一种方法结果图

客户端:

 服务端:

3.1.2 第二种方法--用arg传递IP和端口

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

 #define MSG_STR "Hello zhangkang\n"//添加宏定义,方便write函数中strlen的使用

int main (int argc,char *argv[])
{
	int               sockfd=-1;
    int               rv=-1;
    struct sockaddr_in servaddr;//ipv4 结构体的定义;
    char              *servip=NULL;	
    int               port=0;
    char              buf[1024];//指定读区
	
	if(argc<3)
	{
	    printf("program usage: %s [ServerIP] [ServerPORT]\n",argv[0]);
		return -1;
	}
	servip=argv[1];//第二个参数为目的ip;
	port=atoi(argv[2]);//第三个参数为目的端口;
	
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if (socket<0)
	{
		printf("Creat socker faliure:%s\n",strerror(errno));
		return -2;
	}
	printf("Creat socket[%d] successful!\n",sockfd);
    
	memset(&servaddr,0,sizeof(servaddr));//将定义ipv4的结构体清空;
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(port);
	inet_aton(servip,&servaddr.sin_addr);//写入ipv4结构体中的一些数据;
	
    rv=connect(sockfd(struct sockaddr *)&servaddr,sizeof(servaddr));
	if(rv<0)
	{
	        printf("Connect to server[%s:%d] failure:%s\n",servip,port,strerror(errno));
		return -3;
	}

	printf("Connect to server[%s:%d] successful!",servip,port);
        
	while(1)
	{
	    rv=write(sockfd,MSG_STR,strlen(MSG_STR));
            if(rv<0)
            {
                   printf("Write to server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
	           break;
            }

	    memset(buf,0,sizeof(buf));//将buf清空;
	    rv=read(sockfd,buf,sizeof(buf));
	    if(rv<0)
	    {
	            printf("Read data from  server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
		    break;
	    }
	    else if(rv==0)
	    {
		    printf("Socket[%d] get disconnected\n",sockfd);
		    break;
	    }
	    else if(rv>0)
	    {
		    printf("Read %d bytes data from Server:%s\n",rv,buf);
	            break;
	    }

	}

        close(sockfd);
}	

3.1.2.1第二种方法结果图

客户端:

 服务端:

3.1.3第三种方法--利用getopt_long的选项传递IP和端口

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

 #define MSG_STR "Hello i am zhangkang\n"//添加宏定义,方便write函数中strlen的使用
 
 void print_useage(char *progname)
 {
        printf("%s print_useage:\n",progname)
        printf("-i(--ipaddr):specify server IP address\n");
        printf("-p(--port):specify server  port\n");
        printf("-h(--help):print this help information\n");
        return;
 }

int main (int argc,char *argv[])
{
	int                sockfd=-1;
    int                rv=-1;
    struct sockaddr_in servaddr;//ipv4 结构体的定义;
    char              *servip=NULL;	
    int                port=0;
    char               buf[1024];//指定读区
	int                opt;
    int                idx;
	struct option      opts[] = {
                {"ipaddr",required_argument,NULL,'i'},
                {"port",required_argument,NULL,'p'},
                {"help",no_argument,NULL,'h'},
                {NULL,0,NULL,0}
                                 };
        
        while((opt = getopt_long(argc,argv,"i:a:p:h",opts,&idx)) != -1)
        {
                switch(opt)
                {
                        case 'i':
                                 servip = optarg;
                                 break;
                        case 'p':
                                 port = atoi(optarg);
                                 break;
                        case 'h':
                                print_useage(argv[0]);
                                 return 0;
                        case 'a':
                                 h_alias = optarg;
                                 break;
                }
        }
	
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if (socket<0)
	{
		printf("Creat socker faliure:%s\n",strerror(errno));
		return -1;
	}
	printf("Creat socket[%d] successful!\n",sockfd);
    
	memset(&servaddr,0,sizeof(servaddr));//将定义ipv4的结构体清空;
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(port);
	inet_aton(servip,&servaddr.sin_addr);//写入ipv4结构体中的一些数据;
	
    rv=connect(sockfd(struct sockaddr *)&servaddr,sizeof(servaddr));
	if(rv<0)
	{
	        printf("Connect to server[%s:%d] failure:%s\n",servip,port,strerror(errno));
		return -2;
	}

	printf("Connect to server[%s:%d] successful!",servip,port);
        
	while(1)
	{
	    rv=write(sockfd,MSG_STR,strlen(MSG_STR));
            if(rv<0)
            {
                   printf("Write to server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
	           break;
            }

	    memset(buf,0,sizeof(buf));//将buf清空;
	    rv=read(sockfd,buf,sizeof(buf));
	    if(rv<0)
	    {
	            printf("Read data from  server by sockfd[%d] failure:%s\n",sockfd,strerror(errno));
		    break;
	    }
	    else if(rv==0)
	    {
		    printf("Socket[%d] get disconnected\n",sockfd);
		    break;
	    }
	    else if(rv>0)
	    {
		    printf("Read %d bytes data from Server:%s\n",rv,buf);
	            break;
	    }

	}

        close(sockfd);
}	

 3.1.3.1 第三种方法结果图

客户端:

服务端: 

举报

相关推荐

0 条评论