服务器增强版(TCP)

来源:互联网 发布:lms算法原理及推导 编辑:程序博客网 时间:2024/06/05 02:50

1) 服务器端存在的问题:
*recv会阻塞
解决方法:1、多线程技术
2、 超时返回

2)如何用accept获取客户端IP和端口号
3)TCP通信应用场景:注册统计信息、智能聊天、云计算
4)补充知识
计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换,否则就会出现数据不一致。
  下面是几个字节顺序转换函数:
htonl():把32位值从主机字节序转换成网络字节序
htons():把16位值从主机字节序转换成网络字节序
ntohl():把32位值从网络字节序转换成主机字节序
ntohs():把16位值从网络字节序转换成主机字节序

#include <sys/types.h>          #include <sys/socket.h>#include <arpa/inet.h>#include <stdio.h> #include <string.h>#include <stdlib.h>#include <errno.h>#include <pthread.h>#include <netinet/in.h>void* rcv_data(void* arg);void save_files(const char* str);pthread_mutex_t m;int main(){     pthread_mutex_init(&m,NULL);//创建套接字         int socket_listen=socket(AF_INET,SOCK_STREAM,0);    int opt_val=1;    setsockopt(socket_listen,SOL_SOCKET,SO_REUSEADDR,&opt_val,sizeof(opt_val));                                                     //设置文件 //绑定地址    struct sockaddr_in myaddr;    myaddr.sin_family = AF_INET;    myaddr.sin_addr.s_addr=INADDR_ANY;    myaddr.sin_port=htons(6666);    if(-1==bind(socket_listen,(struct sockaddr*)&myaddr,sizeof(myaddr)))    {                                  perror("bind");        exit(-1);    }//将套接字设置为监听状态    listen(socket_listen,5);    struct timeval rcv_timeout;//设置超时为100ms    rcv_timeout.tv_sec=0;    rcv_timeout.tv_usec=100000;    int sock_conn;    struct sockaddr_in client_addr;    socklen_t len;    while(1)//一直监听    {//接受客户端连接请求        len=sizeof(client_addr);        sock_conn=accept(socket_listen,(struct sockaddr*)&client_addr,&len);        setsockopt(sock_conn,SOL_SOCKET,SO_RCVTIMEO,&rcv_timeout,sizeof(rcv_timeout));//设置超时时间        printf("%s:%d已近连接!\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));        if(sock_conn==-1)        {            perror("accept");            continue;        }        pthread_t tid;        if(0!=pthread_create(&tid,NULL,rcv_data,(void*)sock_conn))        {               perror("pthread_create");            close(sock_conn);        }    }//7、关闭监听套接字    close(socket_listen);    pthread_mutex_destroy(&m);    return 0;}void* rcv_data(void* arg){    pthread_detach(pthread_self());    int sock_conn=(int)arg;    //收发数据    char msg[100];    int ret;    ret=recv(sock_conn,msg,sizeof(msg),0);//0表默认,不加额外控制                                        //阻塞到收到消息,或连接断开     if(ret>0)    {        msg[ret]='\0';        printf("客户端说:%s\n",msg);        save_files(msg);    }    else if(ret==0)    {        printf("接收失败,连接断开\n");    }    else    {        if(errno==EAGAIN || errno==EWOULDBLOCK)        {            printf("接收超时!\n");        }        else        {            printf("其他错误\n");        }    }    strcpy(msg,"收到您的信息");              ret=send(sock_conn,msg,strlen(msg),0);//6、断开连接,即关闭连接套接字    close(sock_conn);    return NULL;}void save_files(const char* str){    pthread_mutex_lock(&m);//保证下面三句话不被打断    FILE* fp=fopen("name.txt","a");    fprintf(fp,"%s\n",str);    fclose(fp);    pthread_mutex_unlock(&m);}//解决阻塞问题//1.主线程接电话,然后分配给其他线程receive//2.超时返回//端口复用//显示对方IP//当客户端send,而服务器端关闭了连接套接字时,服务器进程会收到13号信号,导致进程结束,为了避免这种情况,要用信号处理函数对信号处理。//应用:注册统计信息//群聊天室//云计算
原创粉丝点击