網絡編程練習------簡單雙機通訊

環境:
服務器端:Redhat 6.4 server 64bit
客戶端:    Ubuntu 14.04 64bit

客戶端:
1.    根據傳入的參數建立socket 並與服務器建立連接。
2.    連接成功後,開兩個線程,一個用於接收來自服務器端的消息;另一個用於讀取用戶輸入,再把輸入內容發送到服務器。
3.    當接收到服務器端斷開消息後,退出程序。

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

/*客戶端接收線程*/
void *recvsocket(void *arg)
{
	int st =*(int *)arg;
	char buf[1024];
	int rc = 0;

	while(1)
	{
		memset(buf, 0, sizeof(buf));
		rc = recv(st, buf, sizeof(buf), 0);
		if(rc <= 0)
		{
			exit(0);
		}
		printf("%s", buf);
	}
	return NULL;
}

/*客戶端發送線程*/
void *sendsocket(void *arg)
{
	int st = *(int *)arg;
	char buf[1024];
	int rc =0;

	while(1)
	{
		memset(buf, 0, sizeof(buf));
		read(STDIN_FILENO, buf, sizeof(buf));
		rc = send(st, buf, strlen(buf), 0);
		if(rc <= 0)
		{
			break;
		}
	}
	return NULL;
}

int main(int arg, char **args)
{
	if(arg < 3)
	{
		printf("usage: client ipaddress port\n");
		return -1;
	}

	int port = atoi(args[2]);

	//創建socket
	int st = socket(AF_INET, SOCK_STREAM, 0);
	if(st == -1)
	{
		perror("create socket error:");
		return -2;
	}
	
	//定義一個IP地址結構
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));

	addr.sin_family = AF_INET;		//指定地址結構類型
	addr.sin_port = htons(port);	//指定端口號
	addr.sin_addr.s_addr = inet_addr(args[1]);

	//調用connect連接指定address的服務器
	if(connect(st, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		perror("connect error:");
		return -3;
	}

	pthread_t thrd1, thrd2;
	pthread_create(&thrd1, NULL, recvsocket, &st);
	pthread_create(&thrd2, NULL, sendsocket, &st);
	pthread_join(thrd1, NULL);
	pthread_join(thrd2, NULL);

	return 0;

}


服務器端:
1.    根據傳入的參數建立socket,並等待客戶端連接到來。
2.    當收到一個客戶端請求時,置連接狀態爲1,以表示不再接收其他客戶端連接請求(爲了避免聊天時,不知道發給誰),開兩個線程,一個用於接收客戶端的消息,另一個發送消息。
3.    當服務器接收到客戶端斷開連接消息,把連接狀態置爲0,服務器可以再接收其他客戶端的連接。爲了避免同時改變連接狀態的值,在改變連接狀態的前加鎖。並把發送消息線程取消。

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

/*結構體:用於傳送消息到線程中*/
struct ps_info
{
	int st;
	pthread_t *p;
};

/*標誌:是否已經有客戶端連接*/
int status = 0;
/*鎖*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/*服務器接收線程*/
void *recvsocket(void *arg)
{
	struct ps_info ps1 = *(struct ps_info *)arg;
	int st =ps1.st;
	char buf[1024];
	int rc = 0;

	while(1)
	{
		memset(buf, 0, sizeof(buf));
		rc = recv(st, buf, sizeof(buf), 0);
		if(rc <= 0)
		{
			break;	
		}
		printf("%s", buf);
	}
	pthread_mutex_lock(&mutex);
	status = 0;						//把連接狀態置0
	pthread_mutex_unlock(&mutex);
	pthread_cancel(*ps1.p);			//把發送線程取消
	return NULL;
}

/*服務器發送線程*/
void *sendsocket(void *arg)
{
	int st = *(int *)arg;
	char buf[1024];
	int rc =0;

	while(1)
	{
		memset(buf, 0, sizeof(buf));
		read(STDIN_FILENO, buf, sizeof(buf));
		rc = send(st, buf, strlen(buf), 0);
		if(rc <= 0)
		{
			break;
		}
	}
	return NULL;
}

int main(int arg, char **args)
{
	if(arg < 3)
	{
		printf("usage: client ipaddress port\n");
		return -1;
	}

	int port = atoi(args[2]);

	/*創建socket*/
	int st = socket(AF_INET, SOCK_STREAM, 0);
	if(st == -1)
	{
		perror("create socket error:");
		return -2;
	}
	
	//定義一個IP地址結構
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));

	addr.sin_family = AF_INET;		//指定地址結構類型
	addr.sin_port = htons(port);	//指定端口號
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(st, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		perror("bind error:");
		return -2;
	}

	if(listen(st, 20) == -1)
	{
		perror("listen error:");
		return -2;
	}


	int client_st = 0;
	socklen_t len =0;
	struct sockaddr_in client_addr;
	pthread_t thrd1, thrd2;
	
	while(1)
	{
		memset(&client_addr, 0, sizeof(client_st));
		len = sizeof(client_addr);
		client_st = accept(st, (struct sockaddr *)&client_addr, &len);

		pthread_mutex_lock(&mutex);
		status++;
		pthread_mutex_unlock(&mutex);
		if(status > 1)
		{
			close(client_st);
			continue;
		}

		if(client_st == -1)
		{
			perror("accept error:");
			return -3;
		}

		printf("accept by %s\n", inet_ntoa(client_addr.sin_addr));

		struct ps_info ps1;
		ps1.st = client_st;
		ps1.p = &thrd1;

		pthread_create(&thrd1, NULL, recvsocket, &ps1);
		pthread_detach(thrd1);
		pthread_create(&thrd2, NULL, sendsocket, &client_st);
		pthread_detach(thrd2);
	}

	close(st);

	return 0;

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章