Linux Socket编程---TCP实现多客户端的网络聊天室

本程序实现的功能:

基于linux的网络聊天室

服务器端功能:

1)能够实现同时监听10个客户端

2)新的客户进入聊天室,发送新客户进入的系统消息给所有在线客户

3)在线客户实现基本的群聊功能

4)保存聊天记录,并支持查询聊天记录

5)可以通过终端查看客户之间的聊天状况

客户端功能:

1)能过正常连接服务器

2)通过多线程实现同时进行收发消息

3)保存客户本地聊天记录

4)可以查询本地聊天记录

 

tcpserver.c

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

//给线程传输的信息
struct threadinfo
{	
	//socket
	int my_sock;
	//随机分配的端口号
	int my_port; 
};

//用户数量
int usernum = 0;
//socket数组
int sock_array[10];
//打开文件
int fd;

//发送线程
void *recvsocket(void *arg)
{
	//接受结构体
	struct threadinfo *thread = arg;

	int st = thread->my_sock;
	int port = thread->my_port;
	char receivebuffer[100]; 
	int i;
	int n;
	int length = sizeof(sock_array)/sizeof(sock_array[0]);
	char sendbuffer[100];
	char writebuffer[100];
	
	while(1){
		//接受客户端传回的数据 
		memset(receivebuffer, 0, sizeof(receivebuffer)); 
		n = recv(st, receivebuffer, sizeof(receivebuffer), 0);
		//判断通信是否结束 
		if(n <= 0)
			break;
		printf("来自%d的数据:%s\n", port,receivebuffer);

		//将接受到的聊天记录保存到文件中
		memset(writebuffer, 0, sizeof(writebuffer));
		sprintf(writebuffer,"%d",port);
		strcat(writebuffer,":");
		strcat(writebuffer,receivebuffer);
		strcat(writebuffer,"\n");
		write(fd,writebuffer,sizeof(writebuffer));

		//将接受到的消息发送给出自己外的其他人
		memset(sendbuffer, 0, sizeof(sendbuffer));
		sprintf(sendbuffer,"%d",port);
		strcat(sendbuffer,"说:");
		strcat(sendbuffer,receivebuffer);
		for(i = 0; i<length; i++)
		{
			if(sock_array[i] != st)
			{
				send(sock_array[i], sendbuffer, strlen(sendbuffer), 0);
			}
			
		} 
	}
	return NULL;
}

int main() { 

	//创建套接字 
	int serv_sock = socket(AF_INET, SOCK_STREAM, 0); 
	//将套接字和IP、端口绑定 
	struct sockaddr_in serv_addr; 
	memset(&serv_addr, 0, sizeof(serv_addr));//每个字节都用0填充 
	serv_addr.sin_family = AF_INET; 
	serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
	serv_addr.sin_port = htons(6666); 

	//服务器绑定信息
	if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) { 
		perror("bind failed!"); 
		exit(1); 
	} 

	//进入监听状态,等待用户发起请求 
	printf("监听6666端口...\n"); 

	//创建新的sockaddr_in结构体用于accept
	struct sockaddr_in client_addr; 
	//声明线程数组
	pthread_t thrd[10];
	int client_sock;
	int len = sizeof(client_addr);
	//声明一个结构体,放入下面的数组中
	struct threadinfo my_thread;
	//声明一个结构体数组
	struct threadinfo thread_array[10];
	
	int i;
	char portbuffer[100]; 

	//开始监听,监听10个用户
	listen(serv_sock, 10);
	//pthread_create(&thrd[11], NULL, sendsocket, &sock_array);
	//打开文件
	fd = open("./note.txt", O_CREAT|O_WRONLY|O_APPEND);

	while(1)
	{
		//printf("123");
		
		//accept()接收返回值为客户端的新socket,原来的socket用户继续监听端口 
		client_sock = accept(serv_sock, (struct sockaddr*)&client_addr, &len); 
		if(client_sock < 0) { 
			perror("connect failed!"); 
			exit(1); 
		} 
		printf("欢迎%d用户进入聊天室!\n", client_addr.sin_port);

		//向所有用户发送进入信息
		memset(portbuffer, 0, sizeof(portbuffer));
		sprintf(portbuffer,"%d",client_addr.sin_port);
		strcat(portbuffer,"用户进入聊天室!");
		for(i = 0; i<usernum; i++)
		{
			send(sock_array[i], portbuffer, strlen(portbuffer), 0);
		}
		//username[usernum] = client_addr.sin_port;
		
		//将socket和port放入结构体中   再将这个结构体放入的结构体数组中
		my_thread.my_sock = client_sock;
		my_thread.my_port = client_addr.sin_port;
		thread_array[usernum] = my_thread;
		
		//socket数组
		sock_array[usernum] = client_sock;

		//创建发送线程
		pthread_create(&thrd[usernum], NULL, recvsocket, &thread_array[usernum]);

		//用户数量自增
		usernum++;
			
	}

	//关闭文件
	close(fd);
	//关闭套接字 
	close(client_sock);
	close(serv_sock); 

	return 0; 

} 

tcpclient.c

#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#include<unistd.h> 
#include<arpa/inet.h> 
#include<sys/socket.h> 
#include<pthread.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>


//打开文件
int fd;
//客户端socket
int client_sock;
//文件路径
char path[100];
//段口号
char port[100];

//发送线程
void *sendsocket(void *arg)
{
	//接受socket
	int st = *(int *)arg;
	char sendbuffer[100]; 
	char writebuffer[100];
	while(1){
		//向服务器发送数据 
		memset(sendbuffer, 0, sizeof(sendbuffer)); 
		//printf("请输入消息:");
		scanf("%s",sendbuffer);
		memset(writebuffer, 0, sizeof(writebuffer)); 
		strcat(writebuffer,sendbuffer);
		strcat(writebuffer,"\n");
		//写入文件
		write(fd,writebuffer,sizeof(writebuffer));
		//发送消息
		send(st, sendbuffer, strlen(sendbuffer), 0); 
	}
	return NULL;
}

//接受线程
void *recvsocket(void *arg)
{
	int st = *(int *)arg;
	char receivebuffer[100]; 
	char writebuffer[100];
	int n; 
	while(1){
		//读取服务器传回的数据 
		memset(receivebuffer, 0, sizeof(receivebuffer));
		n = recv(st, receivebuffer, sizeof(receivebuffer), 0);  
		//用于判断通信是否结束 
		if(n<=0)
			break;		
		memset(writebuffer, 0, sizeof(writebuffer)); 
		strcat(writebuffer,receivebuffer);
		strcat(writebuffer,"\n");
		//写入文件
		write(fd,writebuffer,sizeof(writebuffer));
		//输出
		printf("%s\n", receivebuffer);
		
		
	}
	return NULL;
}

int main() { 

	//创建套接字 
	int sock = socket(AF_INET, SOCK_STREAM, 0); 
	//向服务器(特定的IP和端口)发起请求 
	struct sockaddr_in serv_addr; 
	memset(&serv_addr, 0, sizeof(serv_addr));//每个字节都用0填充 
	serv_addr.sin_family = AF_INET; 
	serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
	serv_addr.sin_port = htons(6666); 

	//连接服务器,成功返回0 
	client_sock = connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
	if(client_sock == 0) { 
		printf("服务器连接成功!\n"); 
	} 
	
	//新建一个结构体
	struct sockaddr_in client_addr; 
	memset(&client_addr, 0, sizeof(client_addr));

	int len = sizeof(client_addr);
	//获得本程序的sockaddr_in结构体
	int ti = getsockname(sock, (struct sockaddr*)&client_addr, &len);

	//对字符串拼接得到路径
	sprintf(port,"%d",client_addr.sin_port);
	strcat(path,"./usernote/");
	strcat(path,port);
	//打开文件
	fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_APPEND|O_NONBLOCK);
	if(fd == -1)
	{
		printf("失败!");
	}

	//创建发送接受两个线程  一个接受线程一个发送线程
	pthread_t thrd1, thrd2;
	pthread_create(&thrd1, NULL, sendsocket, &sock);
	pthread_create(&thrd2, NULL, recvsocket, &sock);
	pthread_join(thrd1, NULL);
	pthread_join(thrd2, NULL);

	//关闭文件
	close(fd);
	//关闭套接字 
	close(sock); 

	return 0; 

} 

 

  • 3
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,下面是一个简单的Java示例,演示如何使用Socket编程实现服务器端和客户端程序的编写。 服务器端程序: ```java import java.net.*; import java.io.*; public class Server { public static void main(String[] args) throws IOException { // 创建一个ServerSocket对象,指定监听的端口号 ServerSocket serverSocket = new ServerSocket(12345); // 等待客户端连接 Socket clientSocket = serverSocket.accept(); System.out.println("Got connection from " + clientSocket.getInetAddress().getHostAddress()); // 向客户端发送数据 PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); out.println("Thank you for connecting"); // 关闭客户端连接 out.close(); clientSocket.close(); serverSocket.close(); } } ``` 客户端程序: ```java import java.net.*; import java.io.*; public class Client { public static void main(String[] args) throws IOException { // 创建一个Socket对象,指定服务器的主机名和端口号 Socket socket = new Socket("localhost", 12345); // 接收服务器发送的数据 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println(in.readLine()); // 关闭客户端连接 in.close(); socket.close(); } } ``` 在这个示例中,服务器端和客户端程序都使用了Java的`java.net`包。服务器创建了一个`ServerSocket`对象,并通过`accept()`方法等待客户端连接。在接受到客户端连接后,服务器向客户端发送了一条消息,并关闭了客户端连接。 客户端程序创建了一个`Socket`对象,然后通过`getInputStream()`方法接收服务器发送的一条消息后,关闭了连接。 这只是一个简单的示例,实际应用中,Socket编程可以用于实现各种各样的应用程序,例如聊天程序、文件传输程序等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值