c语言socket 客户端

socket ipv4 客户端
1)创建soket_fd
client_sd = socket(AF_INET,SOCK_STREAM,0);
2)初始化socket信息  socketaddr_in,它里面有3个参数,
 sin_family(这个用来定义使用哪种协议tcp udp)
 port 端口号 int类型
 sin_addr.s_addr  ip地址是个整型,用int_addr()转
 struct socketaddr_in client_sockaddr;
 client_sockaddr.sin_port = htons(port);
 client_sockaddr.sin_family = AF_INET;  tcp
 client_sockaddr.sin_addr.s_addr = inet_addr(ip_src);
3)连接服务端
 int con_rv = connect(client_sd,(struct sockaddr*)&client_sockaddr,sizeof(client_sockaddr));
 如果con_rv =-1 就是连接失败了
4)创建发送线程和连接线程
    pthread_create(线程1指针,线程属性,线程处理函数,给线程的参数)
    pthread_t thrd1; ptread_t thrd2;
    pthread_create(&thrd1,NULL,thread_send,&client_sd);
    pthread_create(&thrd2,NULL,thread_recv,&client_sd);
    pthread_create()==0 表示创建线程ok
    pthread_join(&thrd1,NULL);
    pthread_join(&thrd2,NULL);
5)发送线程
    send(文件id,发送字节,发送字节数,标志);
    send(client_sd,buf,sizeof(buf),0); //返回发送字节数,或者-1(失败)
6)接收线程
    char buf[1024];
    rv = recv(client_sd,buf,sizeof(buf),0); 大于0表示有数据返回

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define BUFFSIZE 1024
#define ERRORCODE  -1

static void *thread_send(void *arg){
    char buf[BUFFSIZE];
    int sd = *(int *)arg;
    while(1){
        memset(buf,0,sizeof(buf));//给buf清零
        read(STDIN_FILENO,buf,sizeof(buf));
        if(send(sd,buf,strlen(buf),0)==-1){
            printf("send error:%s \n",strerror(errno));
            break;
        }
    }
    return NULL;
}

static void *thread_recv(void *arg){
    char buf[BUFFSIZE];
    int sd = *(int *)arg;
    while(1){
        memset(buf,0,sizeof(buf));
        int rv = recv(sd,buf,sizeof(buf),0);
        if(rv<=0){
            if(rv==0){
                printf("server have already full \n");
                exit(0);
            }
            printf("receive error:%s\n",strerror(errno));
            break;
        }
        printf("%s",buf);
    }
    return NULL;
}

int run_client(char *ip_str,int port){
    int client_sd;
    int con_rv;
    pthread_t thrd1,thrd2;
    struct sockaddr_in client_sockaddr; //定义IP地址结构
    client_sd = socket(AF_INET,SOCK_STREAM,0);
    if(client_sd == -1){
        printf("socket create error :%s \n",strerror(errno));
        return ERRORCODE;
    }
    memset(&client_sockaddr,0,sizeof(client_sockaddr));
    client_sockaddr.sin_port = htons(port);                   //set server port
    client_sockaddr.sin_family = AF_INET;                     //set tcp ip
    client_sockaddr.sin_addr.s_addr = inet_addr(ip_str);      //set server ipaddress 将字符串的IP地址转换成int型,客户端要连接的服务端ip地址
    // con_rv = connect(client_sd,(struct sockaddr*)client_sockaddr,sizeof(client_sockaddr));
    con_rv = connect(client_sd, (struct sockaddr*) &client_sockaddr,sizeof(client_sockaddr));
    // 调用connect连接到指定的ip地址和端口号,建立连接后通过socket描述符通讯
    if(con_rv == -1){
        printf("connect error:%s\n",strerror(errno));
        return ERRORCODE;
    }
    if(pthread_create(&thrd1,NULL,thread_send,&client_sd)!=0){
        printf("create thread thrd1 error:%s\n",strerror(errno));
        return ERRORCODE;
    }
    if(pthread_create(&thrd2,NULL,thread_recv,&client_sd)!=0){
        printf("create thread thrd2 error:%s\n",strerror(errno));
        return ERRORCODE;
    }
    pthread_join(thrd2,NULL);
    pthread_join(thrd1,NULL);
    close(client_sd);
    return 0;
}

int main(int argc,char *argv[]){
    if(argc<3){
        printf("Usage:ip port,example:127.0.0.1 8080 \n");
        return ERRORCODE;
    }
    int port = atoi(argv[2]);
    char *ip_str = argv[1];
    run_client(ip_str,port);
    return 0;
}

// 字节流套接口(如tcp套接口)上的read和write函数所表现的行为不同于通常的文件IO。字节流套接口上的读或写输入或输出的字节数可能比要求的数量少,
// 但这不是错误状况,原因是内核中套接口的缓冲区可能已达到了极限。此时所需的是调用者再次调用read或write函数,以输入或输出剩余的字节。
// 可以使用readn函数来实现循环读取以解决这个问题:
ssize_t readn(int fd,void *vptr,size_t n){
    size_t nleft;
    ssize_t nread;
    char *ptr;

    ptr = vptr;
    nleft = n;
    while(nleft>0){
        if((nread==read(fd,ptr,nleft))<0){
            if(errno == EINTR){
                nread = 0;
            }else{
                return (-1);
            }
        }else if(nread ==0){
            break;  //eof
        }
        nleft -= nread;
        ptr +=nread;
    }
    return (n-nleft);  /*return >=0*/
}

参考:【socket】C语言的Socket网络编程_c语言socket-CSDN博客

你可能感兴趣的:(c语言,开发语言)