源代码:
- 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!
}
- 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);
}