linux环境下网络编程—设计并发服务器

利用多线程构建TCP并发服务器,并实现客户端和服务器的传输(多个并发用户同时访问服务器)

 

普通基于TCP的服务器端

创建一个socket调用socket()à绑定IP地址、端口号等信息到socket上调用bind()函数à监听客户端的连接请求,并设置允许的最大连接数调用listen()函数à接收客户端上的连接调用accept()函数à收发数据调用send()recv()/read()write()à关闭网络连接

普通基于TCP的客户端

创建一个socket调用socket()à设置要连接的对方主机地址和端口号等属à连接服务器调用connect()à收发数据调用send()recv()/read()write()à关闭网络连接

多线程构建TCP并发服务器,并实现客户端和服务器的传输(多个并发用户同时访问服务器)

创建一个socket调用socket()à绑定IP地址、端口号等信息到socket上调用bind()函数à监听客户端的连接请求,并设置允许的最大连接数调用listen()函数à接收客户端上的连接调用accept()函数à创建多线程,调用函数收发数据调用send()recv()/read()write()à关闭网络连接

【线程的创建函数原型:int  pthread_create (pthread_t *tidp , const pthread_attr  *attr, void *(*start_rtn)(void),void *arg)】

 

1、tcp_server_pthead.c

#include <stdio.h>   
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<pthread.h>
#define PORT 1234
#define BACKLOG 2 //最大连接数

void *start_routine( void *ptr)
{
int fd = *(int *)ptr;
char buf[100];
int numbytes;
int i,c=0;
printf("this is a new thread,you got connected\n");
printf("fd=%d\n",fd);
if ((numbytes=recv(fd,buf,100,0)) == -1){ //读数据
printf("recv() error\n");
exit(1);
}
char str[100];
char buffer[100];
//将收到的字符串反转 toclient
for(c=0;c<numbytes;c++){
buffer[c]=buf[c];
}
printf("receive message:%s\n",buf);
// printf("numbytes=%d\n",numbytes);
for(i=0;i<numbytes;i++){
str[i]=buf[numbytes-1-i];
}
printf("server will send:%s\n",str);
numbytes=send(fd,str,sizeof(str),0); //发数据
//printf("send numbytes=%d\n",numbytes);
close(fd);
}

int main()
{
int listenfd, connectfd;
struct sockaddr_in server;
struct sockaddr_in client;
int sin_size;
sin_size=sizeof(struct sockaddr_in);
pthread_t thread; //定义一个线程号务器端开始建立sockfd描述符
//创建一个socket 调用socket()函数
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server)); //初始化置0
server.sin_family=AF_INET; //Internet
server.sin_port=htons(PORT);
//server_addr.sin_addr.s_addr=inet_addr("192.168.1.1"); //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip
server.sin_addr.s_addr = htonl (INADDR_ANY); // (将本机器上的long数据转化为网络上的long数据)服务器程序能运行在任何ip的主机上 //INADDR_ANY 表示主机可以是任意IP地址,即服务器程序可以绑定到所有的IP上
// 绑定IP地址、端口号等信息到socket上
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
perror("Bind error.");
exit(1);
}
// 监听客户端的连接请求,并设置允许的最大连接数
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
while(1)
{
// accept 接收客户端上来的连接
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}

printf("You got a connection from %s\n",inet_ntoa(client.sin_addr) );
//创建线程,调用函数,函数内收发数据
pthread_create(&thread,NULL,start_routine,(void *)&connectfd);
}
close(listenfd);// 关闭网络连接
}

2、tcp_client_pthread.c

#include <stdio.h> 
#include <unistd.h>
#include <strings.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 1234
#define MAXDATASIZE 100
char receiveM[100];
char sendM[100];
int main(int argc, char *argv[])
{
int fd, numbytes;
struct hostent *he;
struct sockaddr_in server;
//检查用户输入,如果用户输入不正确,提示用户正确的输入方法
if (argc !=2) {
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
// 通过函数 gethostbyname()获得字符串形式的ip地址,并赋给he使用hostname查询host 名字
if ((he=gethostbyname(argv[1]))==NULL){
printf("gethostbyname() error\n");
exit(1);
}
// 产生套接字fd客户程序开始建立 sockfd描述符
if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){
printf("socket() error\n");
exit(1);
}
/* 客户程序填充服务端的资料 */
bzero(&server,sizeof(server));//初始化置0
server.sin_family = AF_INET; //ipv4
server.sin_port = htons(PORT); (将本机器上的short数据转化为网络上的short数据)端口号
server.sin_addr = *((struct in_addr *)he->h_addr); // IP地址
/* 客户程序发起连接请求 */
if(connect(fd, (struct sockaddr *)&server,sizeof(struct sockaddr))==-1){
printf("connect() error\n");
exit(1);
}
// 向服务器发送数据
printf("send message to server:");
fgets(sendM,100,stdin);
int send_le;
send_le=strlen(sendM);
sendM[send_le-1]='\0';
send(fd,sendM,strlen(sendM),0);
// 从服务器接收数据
if ((numbytes=recv(fd,receiveM,MAXDATASIZE,0)) == -1){
printf("recv() error\n");
exit(1);
}
printf("receive message from server:%s\n",receiveM);
close(fd); /* 结束通讯 */
}