精华内容
下载资源
问答
  • C语言网络编程:recv函数详解

    千次阅读 2019-10-14 23:14:24
    //对于int型的需要将主机端序转换为网络端序,这里转成long型。 std_data . num = htonl ( std_data . num ) ; //将数据std_data强制类型转换后发送 ret = send ( cfd , ( void * ) & std_...
    函数描述
    • 头文件 #include <sys/socket.h>
    • ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    • 函数功能:接收对方发送当数据
      可以同样使用recvfrom函数来接收数据
      ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
      recvfrom函数的最后两个参数写为NULL和0的时候与recv的功能完全一样
    • 返回值:成功返回发送的字节数;失败返回-1,同时errno被设置
    • 函数参数:
      a. sockfd 通信文件描述符
      b. buf 应用缓存,用于存放要发送到数据
      可以是任何类型:结构体,int , char,float,字符串
      c. len buf的大小
      d. flags 一般设置为0,此时send为阻塞式发送
      即发送不成功会一直阻塞,直到被某个信号终端终止,或者直到发送成功为止。
      指定MSG_NOSIGNAL,表示当连接被关闭时不会产生SIGPIPE信号
      指定MSG_DONTWAIT 表示非阻塞发送
      指定MSG_OOB 表示带外数据
    代码实例

    socket.c

    #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>
    
    typedef struct data {
    	char name[30];
    	unsigned int num;
    }Data;
    
    void print_err(char *str, int line, int err_no) {
    	printf("%d, %s :%s\n",line,str,strerror(err_no));
    	_exit(-1);
    }
    int cfd = -1;
    
    //线程函数用于循环从cfd描述符中尝试接收数据
    void *receive(void *pth_arg) {
    	int ret = 0;
    	Data stu_data = {0};
    	while(1) {
    		//初始化结构体变量
    		bzero(&stu_data, sizeof(stu_data));
    		ret = recv(cfd, &stu_data, sizeof(stu_data),0);	
    		if (-1 == ret) {
    			print_err("recv failed",__LINE__,errno);
    		}
    		//接收之后需要将网络端序转换为主机端序
    		printf("student number = %d student name = %s \n",ntohl(stu_data.num),stu_data.name);
    	}
    }
    
    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 = 6789; //设置端口号
    	addr.sin_addr.s_addr = inet_addr("192.168.102.169"); //设置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);
    	}
    
    	/*被动监听客户端发起的tcp连接请求,三次握手后连接建立成功*/
    	struct sockaddr_in caddr = {0};
    	int csize = 0;
    	cfd = accept(skfd, (struct sockaddr*)&caddr, &csize);
    	if (-1 == cfd) {
    		print_err("accept failed", __LINE__, errno);
    	}
    	printf("cport = %d, caddr = %s\n", ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr));
    	
    	//创建子线程用于接收数据
    	pthread_t id;
    	pthread_create(&id,NULL,receive,NULL);
    	
    	//发送数据结构体定义
    	Data std_data = {0};
    	while (1) {
    		printf("stu name:\n");
    		scanf("%s",std_data.name);
    		
    		
    		printf("stu num:\n");
    		scanf("%d",&std_data.num);
    		//对于int型的需要将主机端序转换为网络端序,这里转成long型。
    		std_data.num = htonl(std_data.num);
    		
    		//将数据std_data强制类型转换后发送
    		ret = send(cfd, (void *)&std_data,sizeof(std_data),0);
    		if ( -1 == ret) {
    			print_err("accept failed", __LINE__, errno);
    		}	
    	}
    	
    	return 0;
    }
    

    编译gcc socket.c -lpthread

    展开全文
  • C语言网络编程:accept函数详解

    千次阅读 2019-10-13 18:02:01
    文章目录前言函数描述代码实例如何得到客户端的IP 和 端口号 前言 当使用tcp服务器使用socket创建通信文件描述符,bind绑定了文件...TCP 编程模型如下: 函数描述 #include <sys/socket.h> int accept(i...

    前言

    当使用tcp服务器使用socket创建通信文件描述符,bind绑定了文件描述符,服务器ip和端口号,listen将服务器端的主动描述符转为被动描述符进行监听之后,接口accept通过三次握手与客户端建立连接

    TCP 编程模型如下:
    在这里插入图片描述


    函数描述
    • #include <sys/socket.h>
    • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    • 函数功能:
      被动监听客户端发起的tcp连接请求,三次握手后连接建立成功。客户端connect函数请求发起连接。
      连接成功后服务器的tcp协议会记录客端的ip和端口,如果是跨网通信,记录ip的就是客户端所在路由器的公网ip
    • 返回值:
      成功:返回一个通信描述符,专门用于与连接成功的客户端进行通信。
      失败:返回-1 ,并设置errno
    • 函数参数:
      a. sockfd 已经被listen转为了被动描述符的“套接字文件描述符”,专门用于客户端的监听,入股sockfs没有被listen函数转为被动描述符,则accept是无法将其用来监听客户端连接的。
      套接字文件描述符默认是阻塞的,即如果没有客户端请求连接的时候,此时accept会阻塞,直到有客户端连接;如果不想套接字文件描述符阻塞,则可以创建套接字 socket函数 时指定typeSOCK_NOBLOCK
      b. addrlen表示第二个参数addr的大小,不顾要求给定地址
      c. addr: 用于记录发起连接请求的那个客户端的IP端口
      建立连接时服务器的TCP协议会自动解析客户端发来的数据包,从中获取客户端的IP和端口号
      这里如果服务器应用层需要用到客户端的 IP和端口号,可以给accept指定第二个参数addr,以获取TCP链接时的客户端ip和端口号;如果服务器应用层不需要,则写NULL即可
      addr的结构体类型为 struct sockaddr,在listen函数详解中我们有介绍过,由于这个结构体用起来不是非常方便,我们需要定义struct sockaddr_in结构体来使得sockaddr结构体操作更为便捷。具体使用如下:
      struct sockaddr_in naddr = {0};
       
      int nsize = sizeof(naddr);
      int cfd = accept(sockfd, (struct sockaddr *)&naddr, &nsize);
      
    代码实例
    #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>
    
    void print_err(char *str, int line, int err_no) {
    	printf("%d, %s :%s\n",line,str,strerror(err_no));
    	_exit(-1);
    }
    
    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 = 6789; //设置端口号
    	addr.sin_addr.s_addr = inet_addr("192.168.102.169"); //设置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);
    	}
    
    	/*被动监听客户端发起的tcp连接请求,三次握手后连接建立成功*/
    	int cfd = -1;
    	struct sockaddr_in caddr = {0}; //为应用层获取客户端的IP和端口号
    	int csize = 0;
    	cfd = accept(skfd, (struct sockaddr*)&caddr, &csize);
    	if (-1 == cfd) {
    		print_err("accept failed", __LINE__, errno);
    	}
    	
    	return 0;
    }
    
    如何得到客户端的IP 和 端口号

    比如程序中想要打印客户端的ip和端口号,这里就需要使用到ntohsinet_ntoa函数进行端序转换,因为客户端的端口和ip是服务器的TCP协议,从客户端发送端网络数据包中提取出来,网络数据包的端序属于网络端序,主机接收到数据后如果想要使用的话,就必须从网络端序转为主机端序。

    举例如下:

    struct sockaddr_in caddr = {0};
    
    int csize = sizeof(caddr);
    cfd = accept(sockfd, (struct sockaddr *)&caddr, &csize);
    
    printf("cport = %d, caddr = %s\n", ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr));
    
    展开全文
  • 前面写socket编程各个语句详解的时候就说要上源代码实现客户端和服务器的通信,拖了这么久今天我们就来实现一个客户端与服务器通信的功能,这里要说明的是你在网上找到的实例程序全都是实现很简单的功能,比如客户端...

    如何实现服务器和客户端的通信?(看这里)

    前面写socket编程各个语句详解的时候就说要上源代码实现客户端和服务器的通信,拖了这么久今天我们就来实现一个客户端与服务器通信的功能,这里要说明的是你在网上找到的实例程序全都是实现很简单的功能,比如客户端和服务器可以互相通信,但是局限就是只能你一句我一句的进行通信,还有就是客户端向服务端发送信息,然后服务器接收到以后将原信息发送给客户端,就我的角度来看,后者没有前者功能好,但是两个程序在本质上的过程是一样的。这两种功能的实现在网上都有实例,大家自行google,今天我们要实现的功能就是大体上可以像qq一样对行数发送次数没有限制:(与qq两个人的通信唯一不同的就是当客户端发送完毕后要输入一个“quit‘”来结束信息的录入,服务器同理)

    话不多说,上程序:(下面程序都做了注释,没做注释的地方都比较好理解)
    server.c:
    #include<stdio.h>
    #include<stdlib.h>
    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include<string.h>
    #include<unistd.h>
    int main(int argc, char *argv[])  
    {  
        int server_sockfd;//服务器端套接字  
        int client_sockfd;//客户端套接字  
        int len;  
        struct sockaddr_in my_addr;   //服务器网络地址结构体  
        struct sockaddr_in remote_addr; //客户端网络地址结构体  
        int sin_size;  
        char buf[BUFSIZ];  //数据传送的缓冲区  
        memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零  
        my_addr.sin_family=AF_INET; //设置为IP通信  
        my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上  
        my_addr.sin_port=htons(8000); //服务器端口号  
          
        /*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/  
        if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)  
        {    
            perror("socket");  
            return 1;  
        }  
       
            /*将套接字绑定到服务器的网络地址上*/  
        if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)  
        {  
            perror("bind");  
            return 1;  
        }  
          
        /*监听连接请求--监听队列长度为5*/  
        listen(server_sockfd,5);  
          
        sin_size=sizeof(struct sockaddr_in);  
          
        /*等待客户端连接请求到达*/  
        if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0)  
        {  
            perror("accept");  
            return 1;  
        }  
        printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));  
        len=send(client_sockfd,"Welcome to my server\n",21,0);//发送欢迎信息  
          
        /*接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数*/ 
        while(1)
        {
            while(1)  
            {  
                len = recv(client_sockfd,buf,BUFSIZ,0);  
                buf[len]='\0';  
                if(len > 0)
                {
                   printf("received@: %s\n",buf);  
                }
                if(!strcmp(buf,"quit"))
                {
                    break;
                }
                if(len = 0)
                {
                    exit(0);
                }
                /*if(send(client_sockfd,buf,len,0)<0)  
                {  
                perror("write");  
                return 1;  
                }*/ 
            }
            while(1)
            {
                printf("send@:");
                gets(buf);
                len = send(client_sockfd,buf,sizeof(buf), 0);
                if(!strcmp(buf, "quit"))
                {
                    break;
                }
            }
        }
        
        close(client_sockfd);  
        close(server_sockfd);  
        return 0;  
    }

    client.c:


    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include<string.h>
    #include<unistd.h>
    #include"getstr.h"
    #include<stdlib.h>
      
    int main(int argc, char *argv[])  
    {  
        int client_sockfd;  
        int len;  
        struct sockaddr_in remote_addr; //服务器端网络地址结构体  
        char buf[BUFSIZ];  //数据传送的缓冲区  
        memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零  
        remote_addr.sin_family=AF_INET; //设置为IP通信  
        remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址  
        remote_addr.sin_port=htons(8000); //服务器端口号  
          
        /*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/  
        if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)  
        {  
            perror("socket");  
            return 1;  
        }  
          
        /*将套接字绑定到服务器的网络地址上*/  
        if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)  
        {  
            perror("connect");  
            return 1;  
        }  
        printf("connected to server\n");  
        len=recv(client_sockfd,buf,BUFSIZ,0);//接收服务器端信息  
             buf[len]='\0';  
        printf("%s",buf); //打印服务器端信息  
          
        /*循环的发送接收信息并打印接收信息--recv返回接收到的字节数,send返回发送的字节数*/  
        while(1)  
        {
            while(1)
            {
                printf("Send@:");  
                gets(buf);
                len=send(client_sockfd,buf,strlen(buf),0);  
                if(!strcmp(buf,"quit"))  
                break;  
            }
    
            while(1)
            {
                int len = recv(client_sockfd, buf, BUFSIZ, 0);
                buf[len] = '\0';
                if(len > 0)
                {
                printf("received@: %s\n", buf);
                }
                if(!strcmp(buf,"quit"))
                {
                    break;
                }
                if(len = 0)
                {
                    exit(0);
                }
            }
            /*while((len=recv(client_sockfd,buf,BUFSIZ,0)) > 0)
            {
                buf[len]='\0';  
                printf("received:%s\n",buf);  
            }*/
        }  
        close(client_sockfd);//关闭套接字  
            return 0;  
    } 

    展开全文
  • C语言网络编程:listen函数详解

    千次阅读 2019-10-13 17:36:09
    根据TCP编程模型中我们可以看到之前的socket和bind接口是tcp服务器在为接收客户端的链接做准备,保证tcp的面向字节流,面向连接的可靠通信服务正常进行。接下来的listen端口则为我们进行三次握手与客户端进行链接的...

    前言

    根据TCP编程模型中我们可以看到之前的socketbind接口是tcp服务器在为接收客户端的链接做准备,保证tcp的面向字节流,面向连接的可靠通信服务正常进行。接下来的listen端口则为我们进行三次握手与客户端进行链接的接口。
    TCP编程模型如下
    在这里插入图片描述


    函数描述
    • #include <sys/socket.h>
    • int listen(int sockfd, int backlog);
    • 函数功能:将套接字文件描述符从主动转为被动文件描述符,然后用于被动监听客户端的连接
    • 函数返回值:成功返回0,失败返回-1, errno被设置
    • 参数:
      a. sockfd 表示socket创建的套接字文件描述符
      b. backlog 指定队列的容量
      这个队列用于记录正在连接但是还没有连接完成的客户端,一般设置队列的容量为2,3即可。队列的最大容量需要小于30
    代码实例
    #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>
    
    void print_err(char *str, int line, int err_no) {
    	printf("%d, %s :%s\n",line,str,strerror(err_no));
    	_exit(-1);
    }
    
    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 = 6789; //设置端口号
    	addr.sin_addr.s_addr = inet_addr("192.168.102.169"); //设置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);
    	}
    	
    	return 0;
    }
    
    TCP服务器为什么调用listen

    因为连接请求只能由客户端发起,此时服务端的listen函数是将服务端的主动描述符转为被动描述符,否则无法用于监听客户端的连接。
    TCP服务器监听客户端链接时,使用的是socket返回的“套接字文件描述符”来实现的,但是这个文件描述符默认是主动文件描述符(主动向对方发送数据),所以需要使用listen函数将其转换为被动描述符(只能被动得等待别人主动发送数据,再回应),否则无法用于被动监听客户端。

    展开全文
  • C语言网络编程:send函数详解

    千次阅读 2019-10-13 20:29:31
    //对于int型的需要将主机端序转换为网络端序,这里转成long型。 printf ( "stu num:\n" ) ; scanf ( "%d" , & std_data . num ) ; std_data . num = htonl ( std_data . num ) ; //将数据std_...
  • C语言网络编程:bind函数详解

    千次阅读 2019-10-13 15:15:29
    同样,网络通信的时候发送端计算机和接收端计算机可能端序不一致,比如发送者是大端序,接受者是小端序,如果通信时数据的端序处理不好很可能出现乱码,甚至无法接收到数据。 如果发送者和接受者端序一致则也能够...
  • linux C语言 网络编程教程及源码 一、网络应用层编程 1、Linux网络编程01——网络协议入门 2、Linux网络编程02——无连接和面向连接的区别 3、Linux网络编程03——字节序和地址转换 4、Linux网络编程04——套接字 5...
  • 二、函数详解 1、socket()函数 2、bind()函数 3、listen()、connect()函数 4、accept()函数 5、read()、write()等函数 6、close()函数 7、sockaddr_in和sockaddr详解 三、socket三次握手建立连接 四、...
  • Adaptive Communication Environment (ACE) 是一个高性能、开放源码、面向对象的框架和 C++ 类库,它有助于简化网络应用程序的开发。ACE 工具包包括一个操作系统层和一个封装网络 API 的 C++ 外观(facades)集合。...
  • C语言struct关键字详解

    千次阅读 2016-04-12 23:14:45
    C语言struct关键字详解  struct 是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用。  在网络协议、通信控制、嵌入式系统、驱动开发等地方,我们经常要传送的不是简单的字节流(char 型数组),...
  • 郁金香2013网络授课从零开始学编程(C语言详解)
  • C语言struct关键字详解—结构体

    千次阅读 2015-09-30 18:17:10
    struct 是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用。 在网络协议、通信控制、嵌入式系统、驱动开发等地方,我们经常要传送的不是简单的字节流(char 型...这样做编程复杂,易出错,而且一旦控
  • Linux C语言socket编程详解 避免大家浪费时间找教材以及万恶的积分下载,分析这本书,仅供学习参考: 计算机网络第七版谢希仁pdf下载
  • 要理解本文所谈的技术问题需要读者具有一定C语言编程经验和TCP/IP方面的基本知识。要实习本文的示例,需要Linux下的gcc编译平台支持。 Socket定义 网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 184
精华内容 73
关键字:

c语言网络编程详解

c语言 订阅