哈工大计算机网络实验一 :多线程服务器编程

思路:linux下包含头文件#include <pthread.h>

编译的时候加上参数 -lpthread

对于服务器端,服务器对socket处理的部分与接收客户端字符串的部分分开写,

服务器端的主函数中首先使用socket()函数创建socket,然后使用bind()函数将socket与ip地址和端口绑定,

再调用listen()函数设置为监听端口状态和监听的最大值,最后在while(1)循环里写accept()函数,每接收到一个客户端

就响应并且创建一个线程来处理。


服务器端代码:

server_tcp.c

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <sys/errno.h>
#define BUFFER_SIZE 100
#define LENGTH_OF_LISTEN_QUEUE 5
void * talk_to_client(void *data)
{
	int new_socket = (int)data;
	char buffer[BUFFER_SIZE];
	//bzero(buffer, BUFFER_SIZE);
	int flag;
	int i;
	//接收客户端发送来的信息到buffer中
	while(1)
	{
		if(-1 == (flag = read(new_socket,buffer,32)))
		{
			printf("read from client fail!\n");
		}
		else 
			printf("read from client ok!\n");
		//printf("%s\n",buffer);
		for(i = 0;i<BUFFER_SIZE;i++)
		{
			if(buffer[i]>='a'&&buffer[i]<='z')
				buffer[i]-=32;
		
		}
		if( -1 == write(new_socket,buffer,32))
			printf("write to client fail!\n");
		printf("write to client ok!\n");
		
	}
	//关闭与客户端的连接
	close(new_socket); 
	pthread_exit(NULL);
}

int main()
{
	int flag;
	int i;

	int sfp,nfp;
	struct sockaddr_in s_add,c_add;
	int sin_size;
	unsigned short portnum=0x8888;
	printf("Hello,welcome to my server !\r\n");
	sfp = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == sfp)
	{
		printf("socket fail ! \r\n");
		return -1;
	}
	printf("socket ok !\r\n");

	bzero(&s_add,sizeof(struct sockaddr_in));
	s_add.sin_family=AF_INET;
	s_add.sin_addr.s_addr=htonl(INADDR_ANY);
	s_add.sin_port=htons(portnum);

	if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
	{
		printf("bind fail !\r\n");
		return -1;
	}
	printf("bind ok !\r\n");

	if(-1 == listen(sfp,LENGTH_OF_LISTEN_QUEUE))
	{
		printf("listen fail !\r\n");
		return -1;
	}
	printf("listen ok !\r\n");

	while(1)
	{
		sin_size = sizeof(struct sockaddr_in);
		nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
		if(-1 == nfp)
		{
			printf("accept fail !\r\n");
			return -1;
		}
		printf("accept ok!\r\nServer start get connect from %#x : %#x\r\n",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));

		pthread_t child_thread;
		pthread_attr_t child_thread_attr;
		pthread_attr_init(&child_thread_attr);
		pthread_attr_setdetachstate(&child_thread_attr,PTHREAD_CREATE_DETACHED);
		if( pthread_create(&child_thread,&child_thread_attr,talk_to_client, (void*)nfp) < 0 )
			printf("pthread_create Failed : %s\n",strerror(errno));
	}



	close(sfp);
	return 0;
}

使用命令gcc -o server server_tcp.c -lpthread 编译


客户端代码client_tcp.c

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
	// set str array
	char str[100]={0};
	char c;

	int cfd;
	int recbytes;
	int sin_size;
	char buffer[1024]={0};   
	struct sockaddr_in s_add,c_add;
	unsigned short portnum=0x8888; 
	printf("Hello,welcome to client !\r\n");

	cfd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == cfd)
	{
		printf("socket fail ! \r\n");
		return -1;
	}
	printf("socket ok !\r\n");

	bzero(&s_add,sizeof(struct sockaddr_in));
	s_add.sin_family=AF_INET;
	s_add.sin_addr.s_addr= inet_addr("0.0.0.0");
	s_add.sin_port=htons(portnum);
	printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port);

	if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
	{
		printf("connect fail !\r\n");
		return -1;
	}
	printf("connect ok !\r\n");

	//write data to server
	while(1){
		int j = 0;
		printf("wait for input :");
		memset(str,0,100);
		while((c=getchar())!='\n')	
		{
			str[j] = c;
			j++;

		}
		write (cfd,str,32);
		//printf("%s\n",str);
		if(-1 == (recbytes = read(cfd,buffer,1024)))
		{
			printf("read from server fail !\r\n");
			return -1;
		}
		printf("data from server is :");
		printf("%s\n",buffer);
		//buffer[recbytes]='\0';
		//printf("%s\r\n",buffer);
		//getchar();
	}
	close(cfd);
	return 0;
}

使用命令gcc -o client client_tcp.c编译


多开几个终端,一个终端运行服务器代码和几个终端运行客户端代码测试

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值