两个客户端通过服务器通信(互发)(改进后)

来源:互联网 发布:linux 改时间 编辑:程序博客网 时间:2024/05/20 18:41

  今天把一月5号的那道题改进了一下,两个客户端之间可以循环发送和接受信息。

创建两个客户端A,B,一个服务器。
要求:
客户端A,B都能传小写字母给服务器,服务器接收后转换成大写字母回传给对方客户端(A写的返回给B,B写的返回给A)。
并且传回的信息马上能接收到(在read / write的时候,线程处于阻塞状态,此时如果服务器发消息给客户端,客户端如何马上接收呢?)提示:创建线程,一个线程专门用于读服务器传回的信息,一个线程专门用于发送信息给服务器
效果:客户端A处循环输入一个字母,客户端B立刻能输出一个大写字母。客户端B处循环输入一个字母,客户端A立刻能输出一个大写字母(可以添加说明printf()输入为 / 转换后输出为)

客户端A和B是同一个执行文件

/*********************************************************************File Name:               tcp_net_socket.hAuthor:                         date:Description:            Fuction List:********************************************************************/#ifndef _TCP_NET_SOCKET_H#define _TCP_NET_SOCKET_H#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <signal.h>#include <pthread.h>#include <semaphore.h>#define SERV_PORT 9000extern int tcp_init();extern int tcp_accept(int sfd);extern int tcp_connet();extern void signalhandler(void);#endif
/*********************************************************************File Name:               tcp_net_socket.cAuthor:                          date:Description:            Fuction List:int tcp_init() //用于初始化操作int tcp_accept(int sfd)//用于服务器的接收int tcp_connect(const char* ip)//用于客户端的连接void signalhandler(void)//用于信号处理,让服务器在按下Ctrl+c或Ctrl+\时不会退出********************************************************************/#include "tcp_net_socket.h"//用于初始化操作int tcp_init()  {int sfd = socket(AF_INET, SOCK_STREAM, 0);     //创建套接字if(sfd == -1){perror("socket");return -1;}int ret;struct sockaddr_in serveraddr;memset(&serveraddr,0,sizeof(struct sockaddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SERV_PORT);serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);ret = bind(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr));if(ret == -1){perror("bind");return -1;}ret = listen(sfd,10);           //监听它,并设置允许最大的连接数为10个if(ret == -1){perror("listen");close(sfd);return -1;}return sfd;}//用于服务器的接收int tcp_accept(int sfd){struct sockaddr_in clientaddr;memset(&clientaddr, 0, sizeof(struct sockaddr));int addrlen = sizeof(struct sockaddr);//sfd接受客户端的连接,并创建新的socket为new_fd,将请求连接的客户端的ip、port保存在结构体clientaddr中int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);       if(new_fd == -1){perror("accept");close(sfd);return -1;}printf("%s %d success connet...\n", inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));return new_fd;}//用于客户端的连接int tcp_connect(const char* ip){int ret;int sfd = socket(AF_INET, SOCK_STREAM, 0);     //申请新的socketif(sfd == -1){perror("socket");return -1;}struct sockaddr_in serveraddr;memset(&serveraddr, 0,sizeof(struct sockaddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SERV_PORT);serveraddr.sin_addr.s_addr = inet_addr(ip);    ret = connect(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr));       //将sfd连接至指定的服务器网络地址 serveraddrif(ret == -1){perror("connect");close(sfd);return -1;}return sfd;}//用于信号处理,让服务器在按下Ctrl+c或Ctrl+\时不会退出void signalhandler(void){sigset_t sigSet;sigemptyset(&sigSet);sigaddset(&sigSet,SIGINT);sigaddset(&sigSet,SIGQUIT);sigprocmask(SIG_BLOCK,&sigSet,NULL);}

/*********************************************************************File Name:               tcp_net_client1.cAuthor:                          date:Description:            Fuction List:********************************************************************/#include "tcp_net_socket.h"sem_t MSG1;sem_t MSG2;void* Write(void* fd){int sfd = *((int*)fd);int ret;char buf[2] = {0};while(1){//sem_wait(&MSG1);memset(&buf,0,sizeof(buf));printf("请输入小写字母:\n");scanf("%s",&buf);ret = write(sfd, &buf[0], 1);if(ret == -1){perror("write");close(sfd);return;}//sem_post(&MSG2);}close(sfd); }void* Read(void* fd){int sfd = *((int*)fd);int ret;char buf[2] = {0};while(1){//sem_wait(&MSG2);ret = read(sfd, &buf[0], sizeof(char));if(ret == -1){perror("read");close(sfd);return;}printf("转换后的大写字母为:\n");printf("%c\n",buf[0]);//sem_post(&MSG1);}close(sfd);}int main(int argc, char** argv){if(argc != 2){printf("Usage:./client ip\n");return -1;}pthread_t readID;pthread_t writeID;int ret;int sfd = tcp_connect(argv[1]);sem_init(&MSG1, 0, 1);sem_init(&MSG2, 0, 0);ret = pthread_create(&readID, NULL, Read, (void*)&sfd);if(ret == -1){perror("pthread_create readID");return -1;}ret = pthread_create(&writeID, NULL, Write, (void*)&sfd);if(ret == -1){perror("pthread_create writeID");return -1;}while(1);return 0;}

/*********************************************************************File Name:               tcp_net_server.cAuthor:                          date:Description:            Fuction List:********************************************************************/#include "tcp_net_socket.h"char buf1;char buf2;sem_t MSG1;sem_t MSG2;int cfd[2];void *client1(void* fd){int ret;while(1){ret = read(cfd[0], &buf1, sizeof(char));if(ret == -1){perror("read");close(cfd[0]);return ;}printf("read buf1 success!\n");buf1 = buf1 - 'a' + 'A';ret = write(cfd[1], &buf1, sizeof(char));if(ret == -1){perror("write");close(cfd[1]);return;}printf("write buf2 success!\n");memset(&buf1,0,sizeof(char)); }  close(cfd[0]);}void *client2(void* fd){int ret;while(1){ret = read(cfd[1], &buf2, sizeof(char));if(ret == -1){perror("read");close(cfd[1]);return ;}printf("read buf2 success!\n");buf2 = buf2 - 'a' + 'A';ret = write(cfd[0], &buf2, sizeof(char));if(ret == -1){perror("write");close(cfd[0]);return;}printf("write buf1 success!\n");memset(&buf2,0,sizeof(char));}close(cfd[1]);}int main(){signalhandler();int sfd = tcp_init();int ret;pthread_t client1ID;pthread_t client2ID;int i = 0;while(1){printf ("waiting for client to connect.....\n");cfd[i] = tcp_accept(sfd);if(cfd[i] == -1){return -1;}if(i == 0){pthread_create(&client1ID, NULL, client1, NULL);}if(i == 1){pthread_create(&client2ID, NULL, client2, NULL);}i++;}close(sfd);return 0;}



0 0