TCP套接字网络编程实例(二)

时间:2021-05-12 10:23:47

TCP套接字网络编程实例(二)

采用多线程实现客户端和服务器的聊天功能。OK,上代码。

1.客户端部分:

/*

 * 文件:tcp_client.c

 * 内容:利用TCP实现客户端和服务器的实时聊天。

 * 注  :服务器的端口号及IP,客户端的端口号及IP的输入通过main函数的argcargv来实现。

 * 未输入端口号的话使用默认端口号,服务器为1111,客户端为2222

 * 编译:gcc tcp_client.c -o cli -lpthread

 * 运行:./cli 127.0.0.1 7788(注:这个是服务器端的地址和端口号)

 */

 

#include<stdlib.h>

#include<stdio.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<unistd.h>

#include<string.h>

#include <arpa/inet.h>

#include<errno.h>

#include<time.h>

#include<pthread.h>

 

#define IP "127.0.0.1"

#define SPORT 1111

#define CPORT 2222

#define MAXLEN 1024

 

void* myrecv(void* arg)

{

    int sock_fd = 0,len = 0;

    char buf[MAXLEN] = {'\0'};

    time_t t;

    

    sock_fd = *((int*)arg);

 

    while(1)

    {

        memset(buf,'\0',sizeof(buf)-1);

        len = recv(sock_fd,buf,sizeof(buf) - 1,0);

        if(len > 0)

        {

            t = time(NULL);

            printf("**********************************\n");

            printf("&server:%s\n",buf);

            printf("**********************************\n");

            printf("@%s\n",ctime(&t));

        }

        else if(len < 0)

        {

            printf("recv msg errno,errno code = %d,errno msg = %s\n",errno,strerror(errno));

            break;

        }

        else

        {

            printf("connect server error,it will be quit in 3 seconds later...\n");

            sleep(3);

            exit(EXIT_FAILURE);

        }

    }

}

 

void* mysend(void* arg)

{

    int sock_fd = 0,len = 0;

    char buf[MAXLEN] = {'\0'};

 

    sock_fd = *((int*)arg);

 

    while(1)

    {

        memset(buf,'\0',sizeof(buf));

 

        gets(buf);

        if(!strncasecmp(buf,"quit",4))

        {

            printf("I will close the connect ...\n");

            sleep(1);

            exit(EXIT_FAILURE);

        }

        len = send(sock_fd,buf,strlen(buf),0);

        if(len < 0)

        {

            printf("msg is:%s,send failer,errno is %d,errno message is:%s\n",buf,errno,strerror(errno));

            break;

        }

    }

}

 

 

int main(int argc,char* argv[])

{

    int pid = 0,sock_fd = 0;

    socklen_t len;

    struct sockaddr_in their_addr;

    unsigned int their_port;

    char buf[MAXLEN] = {0};

    pthread_t pthread1,pthread2;

 

    //创建socket

    if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) < 0)

    {

        perror("socket error");

        exit(EXIT_FAILURE);

    }

 

    //发送连接服务器的请求

    memset(&their_addr,0,sizeof(their_addr));

    their_addr.sin_family = AF_INET;

    if(argv[2] && argc >= 3)

        their_port = atoi(argv[2]);

    else

        their_port = SPORT;

    their_addr.sin_port = htons(their_port);

 

    if(argv[1] && argc >=2)

    {

        if(inet_aton(argv[1],(struct in_addr *)&their_addr.sin_addr.s_addr) == 0)

        {

            perror("argv[1]");

            exit(EXIT_FAILURE);

        }

    }

    else

        their_addr.sin_addr.s_addr = inet_addr(IP);

 

    if(connect(sock_fd,(struct sockaddr*)(&their_addr),sizeof(their_addr)) == -1)

    {

        perror("connect error");

        exit(EXIT_FAILURE);

    }

    printf("==============================================\n");

    printf("connect success!\n");

    printf("if you want to leave,please print 'quit'.\n");

    printf("==============================================\n");

 

    pthread_create(&pthread1,NULL,myrecv,(void*)&sock_fd);

    pthread_create(&pthread2,NULL,mysend,(void*)&sock_fd);

 

    pthread_join(pthread1,NULL);

    pthread_join(pthread2,NULL);

    close(sock_fd); //关闭套接字

 

    return 1;

}

2.服务器部分:

/*

 * 文件:tcp_server.c

 * 内容:利用TCP实现客户端和服务器的实时聊天。

 * 注  :服务器的端口号及IP,客户端的端口号及IP的输入通过main函数的argcargv来实现。

 * 未输入端口号的话使用默认端口号,服务器为1111,客户端为2222

 * 编译:gcc tcp_server.c -o ser -lpthread

 * 运行:./ser 127.0.0.1 7788 5

 */

 

#include<stdio.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

#include<time.h>

#include<errno.h>

#include<pthread.h>

#include<arpa/inet.h>

 

#define SPORT 1111

#define CPORT 2222

#define IP "127.0.0.1"

#define MAXLEN 1024

 

struct network_info

{

    struct sockaddr addr;

    int addr_len;

    int sock;

}target = {0,0,0};

 

void* myrecv(void* arg)

{

    int new_fd = 0,len = 0;

    char buf[MAXLEN] = {'\0'};

    time_t t;

    struct network_info netinfo;

    netinfo = *((struct network_info*)arg);

    new_fd = netinfo.sock;

 

    while(1)

    {

        memset(buf,'\0',sizeof(buf)-1);

        len = recv(new_fd,buf,sizeof(buf) - 1,0);

        if(len > 0)

        {

            t = time(NULL);

            printf("&client:%s    @%s\n",buf,ctime(&t));

        }

        else if(len < 0)

        {

            printf("recv msg error,error code = %d,error msg = %s\n",errno,strerror(errno));

            break;

        }

        else

        {

            printf("client is quit\n");

            close(new_fd);

            break;

        }

    }

}

 

void* mysend(void* arg)

{

    int new_fd = 0,len = 0;

    char buf[MAXLEN] = {'\0'};

    struct network_info netinfo;

    netinfo = *((struct network_info*)arg);

 

    new_fd = netinfo.sock;

 

    while(1)

    {

        memset(buf,'\0',sizeof(buf));

 

        gets(buf);

        if(!strncasecmp(buf,"quit",4))

        {

            printf("I will close the connect\n");

            close(new_fd);

            exit(EXIT_FAILURE);

        }

 

        len = sendto(new_fd,buf,strlen(buf),0,(struct sockaddr*)(&(netinfo.addr)),netinfo.addr_len);

        if(len < 0)

        {

            printf("msg is:%s,send failer,errno is %d,errno message is:%s\n",buf,errno,strerror(errno));

            break;

        }

    }

}

 

int main(int argc,char* argv[])

{

    int pid = 0,sock_fd = 0,new_fd = 0;

    socklen_t len;

    struct sockaddr_in self_addr,their_addr;

    unsigned int myport,lisnum;

    char buf[MAXLEN] = {'\0'};

    char ip[17] = {'\0'};

    time_t t;

    pthread_t pthread1,pthread2;

 

    if(argv[2] && argc >=3)

        myport = atoi(argv[2]);

    else

        myport = SPORT;

 

    if(argv[3] && argc >= 4)

        lisnum = atoi(argv[3]);

    else

        lisnum = 3;

 

    //创建套接字

    sock_fd = socket(AF_INET,SOCK_STREAM,0);

    if(sock_fd < 0)

    {

        perror("socket error");

        exit(EXIT_FAILURE);

    }

 

    //绑定自己的端口号

    memset(&self_addr,0,sizeof(self_addr));

    self_addr.sin_family = AF_INET;

    self_addr.sin_port = htons(myport);

    if(argv[1])

        self_addr.sin_addr.s_addr = inet_addr(argv[1]);

    else

        self_addr.sin_addr.s_addr = INADDR_ANY;

 

    if(bind(sock_fd,(struct sockaddr*)&self_addr,sizeof(self_addr)) == -1)

    {

        perror("bind error");

        exit(EXIT_FAILURE);

    }

 

    //监听

    if(listen(sock_fd,lisnum) == -1)

    {

        perror("listen error");

        exit(EXIT_FAILURE);

    }

 

    //接受客户端的连接请求

    memset(&their_addr,0,sizeof(their_addr));

    len = sizeof(their_addr);

    printf("wait for connect\n");

    while(1)

    {

        if((new_fd = accept(sock_fd,(struct sockaddr*)&their_addr,&len)) == -1)

        {

            printf("len=%d,new_fd=%d\n",len,new_fd);

            perror("accept error");

            exit(EXIT_FAILURE);

        }

        printf("=====================================================================\n");

        printf("client connect ok\n");

        printf("though i am a server,but if you want to shutdown,please print 'quit'.\n");

        printf("=====================================================================\n");

        memcpy(&(target.addr),&(their_addr),len);

        target.addr_len = len;

        target.sock = new_fd;

 

        //创建线程用于进程间通信

        pthread_create(&pthread1,NULL,myrecv,(void*)&target);

        pthread_create(&pthread2,NULL,mysend,(void*)&target);

    }

 

    pthread_join(pthread1,NULL);

    pthread_join(pthread2,NULL);

    close(new_fd);

    close(sock_fd); //关闭套接字

 

    return 0;

}

结果:(交叉编译后也可用,那么加上串口编程,加上select,将结构体改为字符串,字符串数据加IP地址等等然后以专有协议形成“报文”,然后和设备以相同协议通讯,似乎。。。)

 

TCP套接字网络编程实例(二)

TCP套接字网络编程实例(二)