socket双向通信

既然能够进行数据传输,那干脆再试着进行双向数据传输,就变成了简单的命令行聊天室一样,但是需要考虑几个问题

1:socket是否是双向数据传输,幸运的是肯定的

2:如果一端既发送又接收,如何调和的问题,不可能串行一前一后吧,这样发送和接收肯定无法都实时刷新结果,最简单的就是弄两个进程或者两个线程,一个发送一个接收,这里分别通过while(1)来持续操作

下面是分别通过多进程实现,code比较简单随意,主要实现功能:

server端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 9999
#define MAXSIZE 4096

int main(){
    int server_sockfd, connect_sockfd;
    struct sockaddr_in server_address;
    char buffer[MAXSIZE];
    int recv_length;
    char eachline[MAXSIZE];
    pid_t pid;

    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
        printf("server create socket failed!\n");
        exit(1);
    }
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(PORT);

    if (bind(server_sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) == -1){
        printf("server bind failed!\n");
        exit(1);
    }

    if (listen(server_sockfd, 10) == -1){
        printf("server listen socket failed!\n");
        exit(1);
    }
    if ((connect_sockfd = accept(server_sockfd, (struct sockaddr *)NULL, NULL)) == -1){
        printf("server connect failed!\n");
        exit(1);
    }
    printf("server connect sucessfully!\n");
    memset(buffer, 0, MAXSIZE);
    if ((pid = fork()) < 0){
        printf("server fork failed!\n");
        exit(1);
    }else if (pid == 0){
        while(1){
            fgets(eachline, MAXSIZE, stdin);
            if (send(connect_sockfd, eachline, strlen(eachline), 0) == -1){
                printf("server send failed!\n");
                exit(1);
            }
        }
    }else{
        while(1){
            if ((recv_length = recv(connect_sockfd, buffer, MAXSIZE, 0)) == -1){
                printf("server recv failed!\n");
                exit(1);
            }
            buffer[recv_length] = '\0';
            printf("server receive data: %s", buffer);
        }
    }
    close(connect_sockfd);
    close(server_sockfd);
    return 0;
}

client端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 9999
#define IPADDR "192.168.1.3"
#define MAXSIZE 4096

int main(int argc, char **argv){
    int client_sockfd;
    char buffer[MAXSIZE];
    int recv_length;
    struct sockaddr_in server_address;
    char eachline[MAXSIZE];
    pid_t pid;

    if ((client_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
        printf("client create socket failed\n");
	exit(1);
    }

    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(PORT);
    if (inet_pton(AF_INET, IPADDR, &server_address.sin_addr) == -1){
        printf("client inet_pton failed!\n");
	exit(1);
    }

    if (connect(client_sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) == -1){
        printf("client connect failed!\n");
	exit(1);
    }
    memset(buffer, 0, MAXSIZE);
    if ((pid = fork()) < 0){
        printf("client fork failed!\n");
	exit(1);
    }else if (pid == 0){
        while(1){
            if ((recv_length = recv(client_sockfd, buffer, MAXSIZE, 0)) == -1){
                printf("client recv failed!\n");
	        exit(1);
	    }
	    buffer[recv_length] = '\0';
            printf("client recv data: %s", buffer);
        }
    }else{
        while(1){
	    fgets(eachline, MAXSIZE, stdin);
            if (send(client_sockfd, eachline, strlen(eachline), 0) == -1){
                printf("client send data failed!\n");
	        exit(1);
            }
            //printf("client send sucessfully!\n");
        }
    }
    close(client_sockfd);
    return 0;
}

这里主进程和子进程一个发送一个接收,分别和对面持续进行数据传输

编译运行,注意的是还是必须要先执行服务端,因为监听listen是在服务端

服务端
[lihui@localhost ~]$ cc -o server server.c
[lihui@localhost ~]$ ./server 
server connect sucessfully!
server receive data: hello
i love you
server receive data: really?
if
sorry
goodbye
光标

客户端
[lihui@localhost ~]$ cc -o client client.c 
[lihui@localhost ~]$ ./client 
hello
client recv data: i love you
really?
client recv data: if
client recv data: sorry
client recv data: goodbye
光标

缺点就是,一段ctrl+c之后,另一方会打印满屏的信息,这是具体while(1)里打印问题

发表回复