分享

tcp 客户端和服务端代码示例

 wusiqi111 2017-12-05


1 #include <sys/socket.h>
2 ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
3 ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);

recv 和send的前3个参数等同于read和write。

flags参数值为0或:

 
flags说明recvsend
 MSG_DONTROUTE绕过路由表查找    •
 MSG_DONTWAIT仅本操作非阻塞   •      •
 MSG_OOB    发送或接收带外数据  •  •
 MSG_PEEK  窥看外来消息  • 
 MSG_WAITALL  等待所有数据   • 

 1. send解析

 sockfd:指定发送端套接字描述符。

 buff:    存放要发送数据的缓冲区

 nbytes:  实际要改善的数据的字节数

 flags:   一般设置为0

 1) send先比较发送数据的长度nbytes和套接字sockfd的发送缓冲区的长度,如果nbytes > 套接字sockfd的发送缓冲区的长度, 该函数返回SOCKET_ERROR;

 2) 如果nbtyes <= 套接字sockfd的发送缓冲区的长度,那么send先检查协议是否正在发送sockfd的发送缓冲区中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送sockfd的发送缓冲区中的数据或者sockfd的发送缓冲区中没有数据,那么send就比较sockfd的发送缓冲区的剩余空间和nbytes

 3) 如果 nbytes > 套接字sockfd的发送缓冲区剩余空间的长度,send就一起等待协议把套接字sockfd的发送缓冲区中的数据发送完

 4) 如果 nbytes < 套接字sockfd的发送缓冲区剩余空间大小,send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把套接字sockfd的发送缓冲区中的数据传到连接的另一端的,而是协议传送的,send仅仅是把buf中的数据copy到套接字sockfd的发送缓冲区的剩余空间里)。

 5) 如果send函数copy成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR; 如果在等待协议传送数据时网络断开,send函数也返回SOCKET_ERROR。

 6) send函数把buff中的数据成功copy到sockfd的改善缓冲区的剩余空间后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个socket函数就会返回SOCKET_ERROR。(每一个除send的socket函数在执行的最开始总要先等待套接字的发送缓冲区中的数据被协议传递完毕才能继续,如果在等待时出现网络错误那么该socket函数就返回SOCKET_ERROR)

 7) 在unix系统下,如果send在等待协议传送数据时网络断开,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的处理是进程终止。

2.recv函数

sockfd: 接收端套接字描述符

buff:   用来存放recv函数接收到的数据的缓冲区

nbytes: 指明buff的长度

flags:   一般置为0

 1) recv先等待s的发送缓冲区的数据被协议传送完毕,如果协议在传送sock的发送缓冲区中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR

 2) 如果套接字sockfd的发送缓冲区中没有数据或者数据被协议成功发送完毕后,recv先检查套接字sockfd的接收缓冲区,如果sockfd的接收缓冲区中没有数据或者协议正在接收数据,那么recv就一起等待,直到把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲区中的数据copy到buff中(注意协议接收到的数据可能大于buff的长度,所以在这种情况下要调用几次recv函数才能把sockfd的接收缓冲区中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的)

 3) recv函数返回其实际copy的字节数,如果recv在copy时出错,那么它返回SOCKET_ERROR。如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

 4) 在unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用 recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。




服务端:
#include <stdio.h>
#include <sys/select.h>

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<errno.h>
#define MAX_MSG_SIZE 1024

int main()
    int ser_sockfd,cli_sockfd; /*sock_fd:监听socket;client_fd:数据传输socket */ 
    struct sockaddr_in ser_addr; /* 本机地址信息 */ 
    struct sockaddr_in cli_addr; /* 客户端地址信息 */ 
    char msg[MAX_MSG_SIZE];/* 缓冲区*/
    ser_sockfd=socket(AF_INET,SOCK_STREAM,0);/*创建连接的SOCKET */
    if(ser_sockfd<0)
    {/*创建失败 */
        fprintf(stderr,"socker Error:%s\n",strerror(errno));
       return 0;
    } 
    /* 初始化服务器地址*/
    int addrlen=sizeof(struct sockaddr_in);
    bzero(&ser_addr,addrlen);
    ser_addr.sin_family=AF_INET;
    ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    ser_addr.sin_port=htons(8888);
    if(bind(ser_sockfd,(struct sockaddr*)&ser_addr,sizeof(struct sockaddr_in))<0)
    { /*绑定失败 */
        fprintf(stderr,"Bind Error:%s\n",(char *)strerror(errno));
        return 0;
    } 
    /*侦听客户端请求*/
    if(listen(ser_sockfd,10)<0)
    {
        fprintf(stderr,"Listen Error:%s\n",(char *)strerror(errno));
        close(ser_sockfd);
        return 0;
    }
    while(1)
    {/* 等待接收客户连接请求*/
        cli_sockfd=accept(ser_sockfd,(struct sockaddr*) &cli_addr,&addrlen);
        if(cli_sockfd<=0)
        {
            fprintf(stderr,"Accept Error:%s\n",(char *)strerror(errno));
        }
        else
        {/*开始服务*/
            recv(cli_sockfd,msg,MAX_MSG_SIZE,0); /* 接受数据*/
           // printf("received a connection from ip=%s,port=%d\n", inet_ntoa(cli_addr.sin_addr.s_addr),ntohs(cli_addr.sin_port));
//   printf("received a connection from port=%d\n",ntohs(cli_addr.sin_port));
            printf("%s\n",msg);/*在屏幕上打印出来 */ 
            strcpy(msg,"hi,I am server!");
            send(cli_sockfd,msg,sizeof(msg),0); /*发送的数据*/
            close(cli_sockfd); 
        }
    }
    close(ser_sockfd);
}

客户端:


#include <stdio.h>
#include <sys/select.h>

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>


int main(int argc, char* argv[])  
{  
int addrlen=sizeof(struct sockaddr_in);
    int sclient = socket(AF_INET, SOCK_STREAM, 0);  
    if(sclient < 0)  
    {  
        printf("invalid socket !");  
        return 0;  
    }  
  
struct sockaddr_in serAddr;  
    serAddr.sin_family = AF_INET;  
    serAddr.sin_port = htons(8888);  
    serAddr.sin_addr.s_addr = inet_addr("127.0.0.1");   
    if (connect(sclient, (struct sockaddr *)&serAddr,addrlen) != 0)  
    {  
        printf("connect error !");  
        close(sclient);  
        return 0;  
    }  
    char * sendData = " hello tcp setver i am  client\n";  
    send(sclient, sendData, strlen(sendData), 0);  
  
    char recData[255];  
    int ret = recv(sclient, recData, 255, 0);  
    if(ret > 0)  
    {  
        recData[ret] = 0x00;  
        printf("recData=%s\r\n",recData);  
    }  
    close(sclient);  

    return 0;  
}  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多