简易QQ聊天室
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42007287/article/details/85340041
实现本功能,仅需了解socket套接字的使用,我已经将socket套接字的监听接受状态封装在了common.c中,相信你看了会有所收获,socket的连接也封装在common.c中。
我们要实现随时接收信息和发送信息两个功能,互不干扰,则需要创建一个线程仅仅接收信息,主进程仅仅发送信息(当然你也可以反过来)。
线程创建很简单。
函数声明:
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t restrict_attr,void(start_rtn)(void),void *restrict arg);
1
参数
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的地址。
最后一个参数是运行函数的参数。
具体使用: 最简单的,线程属性NULL,func函数参数为NULL
pthread_t t //线程id
pthread_create(&t, NULL, func, NULL);//void *func()函数里面的内容是这个线程的具体工作,下面实例中我会用到。
common.c
int connect_socket (int port, char *host) {
int sockfd;
struct sockaddr_in dest_addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
//perror(“socket() error\n”);
return -1;
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.s_addr = inet_addr(host);
if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr))) {
perror(“connect() error”);
return -1;
}
return sockfd;
}
int bind_socket (int port) {
int sockfd;
struct sockaddr_in sock_addr;
struct linger m_sLinger;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror(“socket() error!\n”);
return -1;
}
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(port);
sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char *)&m_sLinger, sizeof(struct linger));
if ((bind(sockfd, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr))) < 0) {
close(sockfd);
perror("bind() error!\n");
return -1;
}
if (listen(sockfd, 20) < 0) {
close(sockfd);
perror("listen() error!\n");
return -1;
}
printf("listening...\n");
return sockfd;
}
server端
#include <stdio.h>
#include “head.h”
#include “common.c”
#define MAX_N 1024
void *send_func () {
int sockfd, socket_listen, port;
port = 6789;
socket_listen = bind_socket(port);
while (1) {
struct sockaddr_in destaddr;
socklen_t len;
if ((sockfd = accept(socket_listen, (struct sockaddr *)&destaddr, &len)) < 0) {
perror(“accept error”);
exit(0);
}
//printf(“connect\n”);
char str[MAX_N];
int a;
memset(str, 0, sizeof(str));
while ((a = recv(sockfd, str, MAX_N, 0)) > 0) {
printf("%s", str);
memset(str, 0, sizeof(str));
}
close(sockfd);
}
}
int main() {
pthread_t send_t;
if (pthread_create(&send_t, NULL, send_func, NULL)) {
perror(“pthread_create error”);
exit(0);
}
int sockfd, socket_listen, port;
port = 8899;
socket_listen = bind_socket(port);
while (1) {
struct sockaddr_in destaddr;
socklen_t len;
if ((sockfd = accept(socket_listen, (struct sockaddr *)&destaddr, &len)) < 0) {
perror("accept error");
exit(0);
}
//printf("connect\n");
char str[MAX_N];
while (1) {
scanf("%[^\n]s", str);
if (strlen(str) == 0 || strcmp(str, "byebye") == 0) {
if (strlen(str)) send(sockfd, str, strlen(str), 0);
getchar();
break;
}
getchar();
strcat(str, "\n");
send(sockfd, str, strlen(str), 0);
memset(str, 0, sizeof(str));
}
close(sockfd);
}
pthread_join(send_t, NULL);
return 0;
}
client端
#include <stdio.h>
#include “head.h”
#include “common.c”
#define PATH_N 50
#define MAX_N 1024
void *send_func () {
int sockfd;
char host[PATH_N];
strcpy(host, “127.0.0.1”) //127.0.0.1是连接本机的ip地址,用ifconfig可以查看主机ip地址,填正确的ip就能连接。
int port = 6789 //对应server端端口
while (1) {
sockfd = connect_socket(port, host); //主动去连接需要知道对方ip和端口
if (sockfd < 0) {
printf(“sockfd < 0\n”);
close(sockfd);
continue;
}
char buffer[MAX_N];
int a;
while(1){
scanf("%[^\n]s", buffer);
if (strlen(buffer) == 0 || strcmp(buffer, “bye”) == 0) {
if (strlen(buffer) == 0) {
getchar();
break;
}
close(sockfd);
return NULL;
}
getchar();
strcat(buffer, “\n”);
send(sockfd, buffer, strlen(buffer), 0);
memset(buffer, 0, sizeof(buffer));
}
close(sockfd);
}
return NULL;
}
int main() {
pthread_t recv_t;
if (pthread_create(&recv_t, NULL, recv_func, NULL)) {
perror(“pthread_create error”);
exit(0);
}
int sockfd;
char host[PATH_N];
strcpy(host, “127.0.0.1”) //127.0.0.1是连接本机的ip地址,用ifconfig可以查看主机ip地址,填正确的ip就能连接。
int port = 8899//对应server端端口
while (1) {
sockfd = connect_socket(port, host);
if (sockfd < 0) {
printf(“sockfd < 0\n”);
close(sockfd);
continue;
}
char buffer[MAX_N];
int a;
while ((a = recv(sockfd, buffer, MAX_N, 0)) > 0) {
if (strcmp(buffer, “byebye”) == 0) {
printf("%s\n", buffer);
close(sockfd);
return 0;
}
printf("%s", buffer);
memset(buffer, 0, sizeof(buffer));
}
close(sockfd);
}
pthread_join(recv_t, NULL);
return 0;
}
socket可能使用的头文件head.h
#include <arpa/inet.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <stdarg.h>
#include <pthread.h>
————————————————
版权声明:本文为CSDN博主「瓶邪写一个夏天」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42007287/article/details/85340041