您的位置:首页 > 运维架构 > Linux

Linux c线程客户端服务器端初探

2016-12-01 15:17 232 查看
这段时间在上嵌入式实验的课,老师正好讲到Linux网络编程这一块,自己也正好在看这一块,所以作为初学者记录一下鼓励一下自己喽!
这里老师对我们的要求是客户端能连续发送数据不需要等待服务器的应答,客户端也能及时收到服务器端连续发送的数据。对此,就要将发送和接收分开,使用线程的方式。
而对服务器端的程序要求是,当接收到字母N开头的字符串时取出N后面的整数,并判断该整数是不是一个幸运素数(4位以上的素数,并且只有一位数字和其它位不同),将判断结果返回给客户端。如客户端发送N4321, 服务器端应答NO, 发送N9999991, 服务器端应答YES。
接下去给出了client.c和server.c程序,仅供参考。


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <pthread.h>

#define PORT 4321
#define BUF_SIZE 1024

int sockfd,sendbytes,recvbytes;
char buf[BUF_SIZE];
struct hostent* host;
struct sockaddr_in serv_addr;
pthread_t thread1;

/***********************************************************************
#include <netdb.h>
#include <sys/socket.h>
struct hostent {
char *h_name;             地址的正式名称
char **h_aliases;         空字节-地址的预备名称的指针
int h_addrtype;           地址类型; 通常是AF_INET
int h_length;             地址的比特长度。
char **h_addr_list;       零字节-主机网络地址指针。网络字节顺序。
};
#define h_addr h_addr_list[0]    h_addr_list中的第一地址。
************************************************************************/

/***********************************************************************
#include <netinet/in.h>
struct sockaddr_in{
sa_family_t sin_family;           16位的地址族
in_port_t sin_port;               16位的端口号
struct in_addr sin_addr;          32位的IP地址
unsigned char sin_zero[8];        填充区,8个字节填充0
}
struct in_addr{
in_addr_t s_addr;
}
************************************************************************/

//pthread function to recieve content from the buffer
void* thfn1(void* arg){
bzero(buf,sizeof(buf));
if((recvbytes = recv(sockfd,buf,BUF_SIZE,0)) == -1){
perror("recv");
exit(1);
}
else{
printf("receive from %d(socket):%s",sockfd,buf);
}
return NULL;
}

int main(int argc,char* argv[]){
//check the argument of the programme
if(argc < 2){
printf("USAGE:./tclient Hostname(or ip address)\n");
exit(1);
}
//check the server address which the argument of the programme imply
if((host = gethostbyname(argv[1])) == NULL){
perror("gethostbyname");
exit(1);
}
//create a socket
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
perror("socket");
exit(1);
}
//init the struct variables of  the serv_addr
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr*)host->h_addr);
bzero(&(serv_addr.sin_zero),8);
//connect to the server
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr)) == -1){
perror("connect");
exit(1);
}
//display the information of the connection
printf("connect to server %s...\nInput the msg to send:\n",argv[1]);
//send and recieve the information from the server circularly
while(1){
bzero(buf,sizeof(buf));      //clean the buffer
if(fgets(buf,BUF_SIZE,stdin)){
if(strcmp(buf,"exit\n") == 0)   //judge if need to break
break;
if((sendbytes = send(sockfd,buf,strlen(buf),0)) == -1){
perror("send");
exit(1);
}
}

if(pthread_create(&thread1,NULL,thfn1,NULL)){  //create a pthread
printf("fail to create a pthread!");
exit(1);
}
}
close(sockfd);
return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>

#define PORT 4321
#define MAX_QUE_CONN_NM 5
#define MAX_SOCK_FD FD_SETSIZE
#define BUFFER_SIZE 1024
#define HOSTLEN 256

//determine whether a prime number
int isprime(int k){
int i;
for(i=2;i<=sqrt(k);i++){
if(k%i == 0)
break;
}
if(i > sqrt(k))
return 1;
else
return 0;
}
//determine whether a lucky number
unsigned char checkNN(int n)
{
//if(n < N/10)
// return 0;

unsigned char res[10],i,cn=0,tn=0;
memset(res,0,10);

while(n > 0)
{
res[n%10] += 1;
n /= 10;
}
for(i=0;i<10;++i)
{
if(res[i] > 1)
++cn;
if(res[i])
++tn;
}
if(tn < 3 && cn < 2)//最多只有2种字符,且只有1种字符个数超过1个
return 1;
else
return 0;
}

int main() {
struct sockaddr_in server_sockaddr, client_sockaddr;
int sin_size, count,k;
fd_set inset, tmp_inset;
int sockfd, client_fd, fd;
char buf[BUFFER_SIZE];                            // 接收、 发送缓冲
struct sockaddr_in scinf[100];                // 客户端地址池
bzero((void *)scinf, sizeof(scinf));
// 创建socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
// 初始化服务器地址结构体
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_sockaddr.sin_zero), 8);
// 为bind设置地址复用
int i = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1) {      //绑定套接字和地址
perror("bind");
exit(1);
}
// 开始侦听客户端连接
if (listen(sockfd, MAX_QUE_CONN_NM) == -1) {
perror("listen");
exit(1);
}
printf("Begin listening...\n");
// 准备非阻塞方式连接多路客户端
FD_ZERO(&inset);                  //清空位向量所有位
FD_SET(sockfd, &inset);       //设置为向量指定位
while (1) {
tmp_inset = inset;
sin_size = sizeof(struct sockaddr_in);
memset(buf, 0, sizeof(buf));
if (!(select(MAX_SOCK_FD, &tmp_inset, NULL, NULL, NULL) > 0)) {//等待网络消息
perror("select"); exit(1);
}
for (fd = 0; fd < MAX_SOCK_FD; ++fd) {
if (FD_ISSET(fd, &tmp_inset) > 0) {
if (fd == sockfd) { // 有客户端连接请求, accept之
if ((client_fd = accept(sockfd, (struct sockaddr*)&client_sockaddr,
&sin_size)) == -1) {
perror("accept"); exit(1);
}
FD_SET(client_fd, &inset);
printf("New connection from %s\n", inet_ntoa(client_sockaddr.sin_addr));
if (client_fd < 100 && client_fd >= 0) // 新连接客户端记入地址池
memcpy((void *)(&scinf[client_fd]), (void *)&client_sockaddr, sin_size);
}
else { // 有客户端数据
if ((count = recv(fd, buf, BUFFER_SIZE, 0)) > 0) { // 接收数据
if (fd >= 0 && fd < 100){
if(buf[0] == 'N'){
k= atoi(buf+1);
if(k >9999 && isprime(k)){
if(checkNN(k))
sprintf(buf,"Yes\n");
}
else
sprintf(buf,"No\n");
}
else
sprintf(buf,"No\n");
}
//printf("Received from %s:\t%s", inet_ntoa(scinf[fd].sin_addr), buf);
if ((count = send(fd, buf, strlen(buf), 0)) == -1) { // 回送数据
perror("send"); exit(1);
}
}
else { // 无法读取数据, 可能连接以断开
if (fd >= 0 && fd < 100)
printf("Client %s has left\n", inet_ntoa(scinf[fd].sin_addr));
memset((void *)(&scinf[client_fd]), 0, sin_size);
close(fd);
FD_CLR(fd, &inset);
}
}
}
}
//bzero(buf,sizeof(buf));
}
close(sockfd);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息