09嵌入式方向 计应(2)班 刘峰
server-client之间的通信
启动服务器程序,客户端把输入发给服务器,服务器再把数据发给其他客户端。客户端利用线程来实现,pthread_create()创建新线程,新线程用来显示buf中的数据,当前线程从pthread_create()返回往下继续执行,阻塞当前进程等待用户输入,并将输入保存到buf中。
/*--------server.c----------------*/
#include
#include tdlib.h>
#include
#include
#include "wrap.c"
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd, xx;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
socklen_t cliaddr_len;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
Listen(listenfd, 20);
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = select(maxfd+1, &rset, NULL, NULL, NULL);
if (nready < 0)
perr_exit("select error");
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE) {
fputs("too many clients\n", stderr);
exit(1);
}
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready == 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i]) < 0)
continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = Read(sockfd, buf, MAXLINE)) == 0) { //读取客户端发送内容
/* connection closed by client */
Close(sockfd); //读取失败关闭连接
FD_CLR(sockfd, &allset);//清除文件描述符
client[i] = -1;//客户端置-1
} else {
xx=sockfd;
int j;
for (j = 0; j <= maxi; j++) {
if (FD_ISSET(sockfd, &rset)) {//把读到的数据发送给每个客户端
if(sockfd!=client[j])
Write(client[j],buf,n);
}
}
}
if (--nready == 0)
break; /* no more readable descriptors */
}
}
}
}
/*---------------client.c------------*/
#include
#include
#include
#include
#include "wrap.c"
#include
#include
#define MAXLINE 80
#define SERV_PORT 8000
pid_t pid;
pthread_t ntid;
pthread_t tid;
int err;
char buf[MAXLINE];
int sockfd, n;
void *thr_fn(sockfe)/*新线程执行*/
{
tid=pthread_self(); //获得当前线程id
if(tid>0){ //判断当前线程是否成功
while (fgets(buf, MAXLINE, stdin) != NULL) {
Write(sockfe, buf, strlen(buf));}//向客户端发数据
}
}
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
fcntl(sockfd,F_SETFL, O_NDELAY);
pid=getpid(); //获得当前进程ID
void *sockfe=(void*)sockfd; //类型转换
err = pthread_create(&ntid,NULL,thr_fn,sockfe);/*创建线程*/
if(err!=0){
fprintf(stderr,"can't create thread:%s\n",strerror(err));
exit(1);} //失败退出
if(pid!=0){ //当前进程执行成功
while(1){
n=Read(sockfd, buf, MAXLINE); //向服务器接收数据
if (n > 0)
Write(STDOUT_FILENO, buf, n); } //读到的数据写进标准输出
}
Close(sockfd);
return 0;
}
执行过程如下:
服务器端
[root@localhost ~]# cd /root/Desktop/
[root@localhost Desktop]# gcc -g server.c -o server
[root@localhost Desktop]# ./server
received from 127.0.0.1 at PORT 60464 //已连接服务器的客户端
received from 127.0.0.1 at PORT 60465
received from 127.0.0.1 at PORT 60466
客户端1
[root@localhost ~]# cd /root/Desktop/
[root@localhost Desktop]# gcc -g client.c -o client -lpthread
[root@localhost Desktop]# ./client
hgjghj
fgfdggg
gagagagfgfg
jjhjjh
nnn
客户端2
[root@localhost ~]# cd /root/Desktop/
[root@localhost Desktop]# gcc -g client.c -o client -lpthread
[root@localhost Desktop]# ./client
hgjghj
fgfdggg
gagagagfgfg
jjhjjh
nnn
启动客户端3
[root@localhost ~]# cd /root/Desktop/
[root@localhost Desktop]# gcc -g client.c -o client -lpthread
[root@localhost Desktop]# ./client
gagagagfgfg
jjhjjh
nnn