1. 程式人生 > >linux伺服器和客戶端中文會話客戶端

linux伺服器和客戶端中文會話客戶端

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


#define PORT 6666
#define MAX_TEXT 512


struct msg_st
{
        long  msg_type;
        char text[BUFSIZ];
};
int gb2312toutf8( char *sourcebuf,size_t sourcelen,char *destbuf,size_t destlen) {   


iconv_t cd;   if( (cd = iconv_open("utf-8","gb2312")) ==0 )     
return -1;   memset(destbuf,0,destlen);   
char **source = &sourcebuf;   
char **dest = &destbuf;
if(-1 == iconv(cd,source,&sourcelen,dest,&destlen))     
return -1;   
iconv_close(cd);   
return 0;   
}


int main(int argc,char **argv)
{
        int ser_sockfd,cli_sockfd;
        int err,n;
        int addlen;
        struct sockaddr_in ser_addr;
        struct sockaddr_in cli_addr;
        char recvline[200],sendline[200];
        char *p;

/*****************************************************************************/
int  msgid  = -1;
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);//檔案儲存許可權是0666
        if(msgid == -1)
        {
                fprintf(stderr, "msgget failed with error: %d\n", errno);
                exit(EXIT_FAILURE);//程式執行失敗
        }


/*****************************************************************************/
        //建立伺服器本地socket監聽
        ser_sockfd=socket(AF_INET,SOCK_STREAM,0);//建立一個socket


        if(ser_sockfd==-1)
        {
                printf("socket error:%s\n",strerror(errno));
                return -1;
        }

int on;
        on = 1;//開啟這個ON
        //它由 TCP 套接字狀態 TIME_WAIT 引起。該狀態在套接字關閉後約保留 2 到 4 分鐘
        //SO_REUSERADDR 允許重用本地地址和埠
        setsockopt( ser_sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );




        bzero(&ser_addr,sizeof(ser_addr));
        ser_addr.sin_family=AF_INET;
        ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);
        ser_addr.sin_port=htons(PORT);
        err=bind(ser_sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));//繫結本地IP和埠
        if(err==-1)
        {
                printf("bind error:%s\n",strerror(errno));
                return -1;
        }


        err=listen(ser_sockfd,5);//監聽埠,這裡範圍不知道


        if(err==-1)
        {
                printf("listen error\n");
                return -1;
        }


        printf("listen the port:\n");
/*****************************************************************************/


        pid_t pid;
        char *message;
        //兩個fork建立了四個執行緒,接收中文亂碼可能是因為大小端的問題
                //還沒弄懂程序的問題
                //這裡僅僅是手機客戶端連線的程序
        pid= fork();
        fork();


        if(pid < 0)
        {
                perror("fork failed\n");
                exit(1);
        }
/*****************************************************************************/
        while(1)
        {


                addlen=sizeof(struct sockaddr);
                //可以連線多個客戶端
                cli_sockfd=accept(ser_sockfd,(struct sockaddr *)&cli_addr,&addlen);//非阻塞


                if(cli_sockfd==-1)
                {
                        printf("accept error\n");
                        break;
                }
                printf("連線上\n");//連線上了,不需要這裡返回資料,手機哪裡就可以查得到


                while(1)
                {
                        memset(recvline,0,200);
                        n=recv(cli_sockfd,recvline,200,0);//阻塞IO
                        if(0==n)
                        {
                                printf("TCP斷開連線\n");
                                break;
                        }


                        recvline[n]='\0';//這裡一定要加字串結束符號嗎?
char line[200];//排除干擾

                        strcpy(line, recvline);
char dest_utf8[200];
//這裡是把utf-8轉換成GB2312
gb2312toutf8(line,strlen(line),dest_utf8,200);

printf("\nreceive data :%s\n",dest_utf8);
/*****************************************************************************/
                        if(strstr(recvline,"phone"))
                        {
//建立訊息佇列
 
struct msg_st data;
int  msgid  = -1;
msgid  = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
//exit(EXIT_FAILURE);//沒寫???有問題不???
}
                                data.msg_type = 1;
 
                                strcpy(data.text, recvline);
                               
                                if(msgsnd(msgid, (void*)&data, 200, IPC_NOWAIT) == -1)//不能大於1024
                                {
                                        fprintf(stderr, "\n%d  %s\n",errno,strerror(errno));
                                        //exit(EXIT_FAILURE);
                                }
else
{
printf("\n加入訊息佇列成功\n");
}
                        }
/*****************************************************************************/
                        else
                        {
                                //可以過濾掉錯誤的資訊
                                char sendline[]="the error data\n";
                                send(cli_sockfd,sendline,strlen(sendline),0);//傳送失敗>才返回-1,關掉了如何判斷
                        }
                        usleep(50);
                }
                close(cli_sockfd);
        }
        close(ser_sockfd);


        return 0;
}