计算机网络 实验七 socket编程(文末附源码)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
源代码:

  1. server.c
    编译命令:gcc server.c -o server -lpthread
#include <stdlib.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h> //pthread_t , pthread_attr_t and so on.
#include <stdio.h>
#include <netinet/in.h> //structure sockaddr_in
#include <arpa/inet.h>	//Func : htonl; htons; ntohl; ntohs
#include <assert.h>		//Func :assert
#include <string.h>		//Func :memset
#include <unistd.h>		//Func :close,write,read
#include <time.h>
#include <sys/syscall.h>

#define SOCK_PORT 3654
#define BUFFER_LENGTH 4096
#define MAX_CONN_LIMIT 512 //MAX connection limit

struct client
{
	int fd;
	char ip[20];
	int port;
	pthread_t tid;
	int number;
};

struct client client_list[MAX_CONN_LIMIT];
int connection_number = 0;
static void Data_handle(void *sock_fd); //Only can be seen in the file

void record(pthread_t tid, int fd)
{
	client_list[connection_number].fd = fd;
	client_list[connection_number].tid = tid;
	client_list[connection_number].number = connection_number;

	struct sockaddr local_addr;
	struct sockaddr addr;
	socklen_t len = sizeof(addr);
	if (getsockname(fd, &local_addr, &len) == 0)
	{
		struct sockaddr_in *sin = (struct sockaddr_in *)(&local_addr);

		char addr_buffer[INET_ADDRSTRLEN];
		void *tmp = &(sin->sin_addr);
		if (inet_ntop(AF_INET, tmp, addr_buffer, INET_ADDRSTRLEN) != NULL)
		{
			strcpy(client_list[connection_number].ip, addr_buffer);
			client_list[connection_number].port = sin->sin_port;
		}
	}

	connection_number++;
}

int main()
{
	int sockfd_server;
	int sockfd;
	int fd_temp;
	struct sockaddr_in s_addr_in;
	struct sockaddr_in s_addr_client;
	int client_length;

	sockfd_server = socket(AF_INET, SOCK_STREAM, 0); //ipv4,TCP
	assert(sockfd_server != -1);

	//before bind(), set the attr of structure sockaddr.
	memset(&s_addr_in, 0, sizeof(s_addr_in));
	s_addr_in.sin_family = AF_INET;
	s_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); //trans addr from uint32_t host byte order to network byte order.
	s_addr_in.sin_port = htons(SOCK_PORT);		   //trans port from uint16_t host byte order to network byte order.
	fd_temp = bind(sockfd_server, (struct scokaddr *)(&s_addr_in), sizeof(s_addr_in));

	if (fd_temp == -1)
	{
		fprintf(stderr, "bind error!\n");
		exit(1);
	}

	fd_temp = listen(sockfd_server, MAX_CONN_LIMIT);

	if (fd_temp == -1)
	{
		fprintf(stderr, "listen error!\n");
		exit(1);
	}

	while (1)
	{
		printf("waiting for new connection...\n");
		pthread_t thread_id;
		client_length = sizeof(s_addr_client);

		//Block here. Until server accpets a new connection.
		sockfd = accept(sockfd_server, (struct sockaddr_ *)(&s_addr_client), (socklen_t *)(&client_length));

		if (sockfd == -1)
		{
			fprintf(stderr, "Accept error!\n");
			continue; //ignore current socket ,continue while loop.
		}

		printf("A new connection occurs!\n");

		if (pthread_create(&thread_id, NULL, (void *)(&Data_handle), (void *)(&sockfd)) == -1)
		{
			fprintf(stderr, "pthread_create error!\n");
			break; //break while loop
		}
	}

	//Clear
	int ret = shutdown(sockfd_server, SHUT_WR); //shut down the all or part of a full-duplex connection.
	assert(ret != -1);

	printf("Server shuts down\n");
	return 0;
}

static void Data_handle(void *sock_fd)
{
	int fd = *((int *)sock_fd);
	int i_recvBytes;
	char data_recv[BUFFER_LENGTH];
	char data_send[BUFFER_LENGTH] = {0};

	record(pthread_self(), fd);

	while (1)
	{
		printf("waiting for request...\n");
		//Reset data.
		memset(data_recv, 0, BUFFER_LENGTH);

		i_recvBytes = recv(fd, data_recv, BUFFER_LENGTH, 0);

		if (i_recvBytes == 0)
		{
			printf("Maybe the client has closed\n");
			break;
		}

		if (i_recvBytes == -1)
		{
			fprintf(stderr, "read error!\n");
			break;
		}

		if (strcmp(data_recv, "quit") == 0)
		{
			printf("Quit command!\n");
			send(fd, "connection closed", strlen(data_send), 0);

			break; //Break the while loop.
		}

		printf("read from client : %s\n", data_recv);
		if (data_recv[0] == '#' && data_recv[1] == '#' && data_recv[2] == '#' && data_recv[3] == '#')
		{
			char infomation[5] = {0};
			strncpy(infomation, data_recv + 9, 4);

			if (strcmp(infomation, "time") == 0)
			{
				time_t now;
				struct tm *tm_now;
				time(&now);
				tm_now = localtime(&now);

				sprintf(data_send, "now datetime: %d-%d-%d %d:%d:%d\n", tm_now->tm_year + 1900, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
			}
			else if (strcmp(infomation, "name") == 0)
			{
				char host_name[1024] = {0};
				gethostname(host_name, 1024);
				sprintf(data_send, "The server host name: %s", host_name);
				printf("%s", host_name);
			}
			else
			{
				int current_number = 0;
				strcpy(data_send, "tid\t\t\tip\tport\tnumber\n");

				for (int i = 0; i < connection_number; i++)
				{
					char temp[50] = {0};
					sprintf(temp, "%u\t%s\t%d\t%d\n", client_list[i].tid, client_list[i].ip, client_list[i].port, client_list[i].number);
					strcat(data_send, temp);

					if (client_list[i].tid == pthread_self())
					{
						current_number = client_list[i].number;
					}
				}

				char temp[50];
				sprintf(temp, "And your client's number is: %d\n", current_number);
				strcat(data_send, temp);
			}

			printf("The data sent:\n%s", data_send);
		}
		else
		{
			int target_number = 0, source_number = 0;
			int index = 0;
			for (;; index++)
			{
				if (data_recv[index] != ' ')
				{
					target_number *= 10;
					target_number += data_recv[index] - '0';
				}
				else
				{
					break;
				}
			}
			printf("The information that client want to say to client number %d is:\n%s\n", target_number, data_recv + index + 6);

			for (int i = 0; i < connection_number; i++)
			{
				if (fd == client_list[i].fd)
				{
					source_number = client_list[i].number;
					break;
				}
			}

			char temp[BUFFER_LENGTH] = {0};
			sprintf(temp, "#### The client number %d sends you a message:\n%s", source_number, data_recv + index + 6);
			if (send(client_list[target_number].fd, temp, strlen(temp), 0) == -1)
			{
				strcpy(data_send, "Sending error!\n");
			}
			else
			{
				strcpy(data_send, "The server has received your message.\n");
			}
		}

		if (send(fd, data_send, strlen(data_send), 0) == -1)
		{
			printf("The client may have been closed!\n");
			break;
		}
	}

	//Clear
	printf("terminating current client_connection...\n");
	printf("The connection is successfully closed!\n");
	close(fd);			//close a file descriptor.
	pthread_exit(NULL); //terminate calling thread!
}
  1. client.c
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h> //pthread_t , pthread_attr_t and so on.
#include <stdio.h>
#include <netinet/in.h> //structure sockaddr_in
#include <arpa/inet.h>  //Func : htonl; htons; ntohl; ntohs
#include <assert.h>     //Func :assert
#include <string.h>     //Func :memset
#include <unistd.h>     //Func :close,write,read

#define SOCK_PORT 3654
#define BUFFER_LENGTH 4096

void initial()
{
    printf("Connection success!! Port: 3654\n");
    printf("This program is developed by Leming Shen, 3180103654,\n");
    printf("College of Computer Science and Technology, Zhejiang University.\n");
    printf("To get more inforation, email to me at ZJU.SLM@gmail.com\n\n");

    printf("This is a simple socket program.\n");
    printf("Here are the choices you have:\n");
    printf("1)\tGet information about the server.\n");
    printf("2)\tSend information about the server.\n");
    printf("3)\tQuit the client program.\n");
}

static void Data_handle(void *sock_fd); //Only can be seen in the file

int main()
{
    int sockfd, choice = 0, tempfd;
    struct sockaddr_in s_addr_in;
    char data_send[BUFFER_LENGTH];
    char data_recv[BUFFER_LENGTH];

    memset(data_send, 0, BUFFER_LENGTH);
    memset(data_recv, 0, BUFFER_LENGTH);

    sockfd = socket(AF_INET, SOCK_STREAM, 0); //ipv4,TCP

    if (sockfd == -1)
    {
        fprintf(stderr, "socket error!\n");
        exit(1);
    }

    pthread_t thread_id;
    if (pthread_create(&thread_id, NULL, (void *)(&Data_handle), (void *)(&sockfd)) == -1)
    {
        fprintf(stderr, "pthread_create error\n");
        printf("Cannot communicate with other clients.\n");
        exit(1);
    }

    char ip[20] = {0};
    while (1)
    {
        printf("Please input the IP and Port that you want to connect\nThe ip: ");
        int port;

        gets(ip);
        printf("And the port: ");
        scanf("%d", &port);
        if (port != 3654)
        {
            printf("Can not connect to this server, please input again.\n");
            printf("The suggested server is: 127.0.0.1:3654\n");
        }
        else
        {
            break;
        }
    }

    //before func connect, set the attr of structure sockaddr.
    memset(&s_addr_in, 0, sizeof(s_addr_in));
    s_addr_in.sin_addr.s_addr = inet_addr(ip); //trans char * to in_addr_t
    s_addr_in.sin_family = AF_INET;
    s_addr_in.sin_port = htons(SOCK_PORT);

    tempfd = connect(sockfd, (struct sockaddr *)(&s_addr_in), sizeof(s_addr_in));

    if (tempfd == -1)
    {
        fprintf(stderr, "Connect error! \n");
        exit(1);
    }

    initial();

    while (1)
    {
        sleep(1);
        printf("\nNow please input the number of command: ");
        scanf("%d", &choice);

        if (choice == 3)
        {
            printf("Bye bye!\n");
            strcpy(data_send, "quit");
            break;
        }
        else if (choice == 2)
        {
            int client_number;
            printf("Please input the client's number you want to: ");
            scanf("%d", &client_number);
            printf("Please input something you want to send to the server:\n");
            getchar();
            char temp[BUFFER_LENGTH - 5] = {0};
            gets(temp);
            sprintf(data_send, "%d send %s", client_number, temp);
        }
        else
        {
            int temp_choice;
            printf("Which information of the server you want to get?\n");
            printf("1 for server time, 2 for server name, 3 for client list\n");
            printf("Now please input your choice: ");
            scanf("%d", &temp_choice);

            if (temp_choice == 1)
            {
                strcpy(data_send, "#### get time ####");
            }
            else if (temp_choice == 2)
            {
                strcpy(data_send, "#### get name ####");
            }
            else
            {
                strcpy(data_send, "#### get list ####");
            }
        }

        tempfd = send(sockfd, data_send, BUFFER_LENGTH, 0);

        if (tempfd == -1)
        {
            fprintf(stderr, "write error\n");
            exit(0);
        }

        /*tempfd = recv(sockfd, data_recv, BUFFER_LENGTH, 0);
        assert(tempfd != -1);
        printf("The information from the server:\n%s\n", data_recv);

        if (strcmp(data_recv, "connection closed") == 0)
        {
            break;
        }*/

        memset(data_send, 0, BUFFER_LENGTH);
        memset(data_recv, 0, BUFFER_LENGTH);
    }

    int ret = shutdown(sockfd, SHUT_WR);
    assert(ret != -1);

    return 0;
}

static void Data_handle(void *sock_fd)
{
    char data_recv[BUFFER_LENGTH];
    int i_recvBytes, fd = *((int *)sock_fd);

    while (1)
    {
        memset(data_recv, 0, BUFFER_LENGTH);

        i_recvBytes = recv(fd, data_recv, BUFFER_LENGTH, 0);

        if (i_recvBytes > 0)
        {
            if (data_recv[0] == '#')
            {
                printf("\nThe data from another client:\n%s\n", data_recv);
            }
            else
            {
                printf("The information from the server:\n%s\n", data_recv);
            }
        }

        if (strcmp(data_recv, "connection closed") == 0)
        {
            break;
        }

        memset(data_recv, 0, BUFFER_LENGTH);
    }

    int ret = shutdown(sock_fd, SHUT_WR);
    assert(ret != -1);

    exit(0);
}
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值