今天把一月5号的那道题改进了一下,两个客户端之间可以循环发送和接受信息。
创建两个客户端A,B,一个服务器。
要求:
客户端A,B都能传小写字母给服务器,服务器接收后转换成大写字母回传给对方客户端(A写的返回给B,B写的返回给A)。
并且传回的信息马上能接收到(在read / write的时候,线程处于阻塞状态,此时如果服务器发消息给客户端,客户端如何马上接收呢?)提示:创建线程,一个线程专门用于读服务器传回的信息,一个线程专门用于发送信息给服务器
效果:客户端A处循环输入一个字母,客户端B立刻能输出一个大写字母。客户端B处循环输入一个字母,客户端A立刻能输出一个大写字母(可以添加说明printf()输入为 / 转换后输出为)
客户端A和B是同一个执行文件
/*********************************************************************
File Name: tcp_net_socket.h
Author: 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 9000
extern int tcp_init();
extern int tcp_accept(int sfd);
extern int tcp_connet();
extern void signalhandler(void);
#endif
/*********************************************************************
File Name: tcp_net_socket.c
Author: 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); //申请新的socket
if(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连接至指定的服务器网络地址 serveraddr
if(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.c
Author: 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.c
Author: 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;
}