1、server.c
#include "wrap.h"
#include <pthread.h>
#include <ctype.h>
#include <strings.h>
void *callback(void *arg)
{
int *cfd = (int *)arg;
printf("pthread %ld running...\n", pthread_self());
while(1){
char buf[BUFSIZ];
int n = Readn(*cfd, buf, BUFSIZ);
if (n <= 0){
close(*cfd);
pthread_exit(NULL);
}
int i = n;
while(i--){
buf[i] = toupper(buf[i]);
}
write(*cfd, buf, n);
}
return NULL;
}
#define SEV_PORT 3000
int main(){
// 1、socket
int sfd = Socket(AF_INET, SOCK_STREAM, 0);
// 2、bind
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SEV_PORT);
Bind(sfd, &addr, sizeof(addr));
// 3、listen
Listen(sfd, 128);
// 4、accept
int cfds[256];
int n = 0;
while(1){
struct sockaddr_in c_addr;
socklen_t len = sizeof(c_addr);
bzero(&c_addr, sizeof(c_addr));
cfds[n] = Accept(sfd, &c_addr, &len);
char buf[BUFSIZ];
printf("Client connected -- ip:%s, port:%d\n", inet_ntop(AF_INET, &c_addr.sin_addr.s_addr, buf, BUFSIZ), ntohs(c_addr.sin_port));
pthread_t thread;
int ret = pthread_create(&thread, NULL, callback, cfds + n);
if (ret < 0){
perror("pthread create error");
exit(1);
}
n++;
pthread_detach(thread);
}
}
wrap.h
#ifndef _WRAP_H_
#define _WRAP_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int Socket(int domain, int type, int protocol);
int Bind(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen);
int Listen(int sockfd, int backlog);
int Accept(int sockfd, struct sockaddr_in *addr, socklen_t *addrlen);
int Connect(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen);
ssize_t Readn(int fd, void *buf, size_t count);
#endif
wrap.c
#include "wrap.h"
#include <errno.h>
void print_err(const char* descript)
{
perror(descript);
exit(1);
}
int Socket(int domain, int type, int protocol)
{
int ret = socket(domain, type, protocol);
if (ret < 1) print_err("socket error");
return ret;
}
int Bind(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen)
{
int ret = bind(sockfd, (struct sockaddr *)addr, addrlen);
if (ret < 0) print_err("bind error");
return ret;
}
int Accept(int sockfd, struct sockaddr_in *addr, socklen_t *addrlen)
{
int sfd;
again:
sfd = accept(sockfd, (struct sockaddr *)addr, addrlen);
if (sfd < 0){
// 阻塞等待,考虑被信号中断的情况
if ((errno == ECONNABORTED) || (errno == EINTR)){
goto again;
}else{
print_err("accept error");
}
}
return sfd;
}
int Listen(int sockfd, int backlog)
{
int ret = listen(sockfd, backlog);
if (ret < 0) print_err("listen error");
return ret;
}
int Connect(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen)
{
int ret = connect(sockfd, (struct sockaddr *)addr, addrlen);
if (ret < 0) print_err("connect error");
return ret;
}
ssize_t Readn(int fd, void *buf, size_t count)
{
size_t readed = 0;// 已读数
size_t remain = count;// 未读数
while(remain > 0){
int n = read(fd, buf+readed, remain);
if (n < 0){ // 异常处理
if (errno == EINTR){
n = 0;// 信号中断,继续循环
}else{
return n;// 异常情况直接返回
}
}else if (n < remain){
remain -= n;
break;
}
readed += n;
remain -= n;
}
return count - remain;// 返回应读数-未读数
}
运行结果:
parallels@ubuntu:~/Linux/mp-socket$ ./server.out
Client connected -- ip:10.211.55.2, port:49543
Client connected -- ip:10.211.55.2, port:49546
^C
parallels@ubuntu:~/Linux/mp-socket$
2、client.c
#include "wrap.h"
#include <unistd.h>
#include <string.h>
#define SERVER_PORT 3000
#define SERVER_IP "10.211.55.6"
int main(){
int sfd = Socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in svr_addr;
svr_addr.sin_family = PF_INET;
svr_addr.sin_port = htons(SERVER_PORT);
// 清0操作
memset(&svr_addr.sin_addr.s_addr, 0, sizeof(svr_addr.sin_addr.s_addr));
// 将点分十进制字符串转为字节序
inet_pton(PF_INET, SERVER_IP, &svr_addr.sin_addr.s_addr);
// 发起网络连接
Connect(sfd, &svr_addr, sizeof(svr_addr));
printf("服务器连接成功!\n");
char buf[BUFSIZ];
while(1){
// 读取输入流
fgets(buf, sizeof(buf), stdin);
// 写入套接字
write(sfd, buf, strlen(buf));
// 读取服务器响应
int n = read(sfd, buf, sizeof(buf));
// 将结果输出到标准输出流
write(STDOUT_FILENO, buf, n);
}
close(sfd);
return 0;
}
运行结果
yusian@SianMac2:~/Linux/socket$ ./client.out
服务器连接成功!
asdf
ASDF
^C
yusian@SianMac2:~/Linux/socket$