基于昨天的极(jian)简(lou)的文字聊天的服务器做个客户端。
浅尝
与服务器相比,客户端用了一个新系统调用connect
,顾名思义,它是用来与服务器建立连接的。
代码演示
因为使用了线程,所以注意编译时要加上-lpthread
。
主线程用于接收用户输入,子线程专门用来显示服务器发来的对话记录。
#include <unistd.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <pthread.h>
static int running = 1;
static void *thread_func(void *arg){
int fd = *(int *)arg;
char rvbuf[1024];
while (running){
ssize_t size = recv(fd, rvbuf, sizeof(rvbuf), 0);
if (size <= 0){
printf("logout.\n");
running = 0;
return;
}
rvbuf[sizeof(rvbuf)/sizeof(char) - 1] = '\0';
printf("%s", rvbuf);
fflush(stdout);
}
}
int main(int argc, char **argv){
int fd, ret, line;
pthread_t tid;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
addr.sin_addr.s_addr = htons(INADDR_ANY);
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
line = __LINE__;
goto ERROR;
}
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))){
line = __LINE__;
goto ERROR_CLOSE_FD;
}
ret = pthread_create(&tid, NULL, thread_func, (void*)&fd);
if (ret){
line = __LINE__;
pthread_cancel(tid);
pthread_join(tid, NULL);
goto ERROR_CLOSE_FD;
}
while (running){
char rvbuf[512];
ssize_t size;
int len;
scanf("%s", rvbuf);
len = strlen(rvbuf) + 1;
size = send(fd, rvbuf, len, MSG_NOSIGNAL);
if (size != len){
running = 0;
line = __LINE__;
pthread_cancel(tid);
pthread_join(tid, NULL);
printf("logout.\n");
}
}
return 0;
ERROR_CLOSE_FD:
close(fd);
ERROR:
printf("error@%d, %s\n", line, strerror(errno));
exit(EXIT_FAILURE);
}
输出
服务器
0 users online.
1 users online.
2 users online.
用户0
Please wait for your friend...
Your friend is online now.
hi
[1542109526s:788781us]0:
hi
[1542109533s:125340us]1:
hihi
用户1
Your friend is online now.
[1542109526s:788781us]0:
hi
hihi
[1542109533s:125340us]1:
hihi