基本的局域网聊天

  局域网聊天TCP服务端:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <thread>
#include <iostream>
#define PORT 7000
#define QUEUE 20
int conn;
void thread_task() {
} int main() {
//printf("%d\n",AF_INET);
//printf("%d\n",SOCK_STREAM);
int ss = socket(AF_INET, SOCK_STREAM, );
//printf("%d\n",ss);
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
//printf("%d\n",INADDR_ANY);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-) {
perror("bind");
exit();
}
if(listen(ss, QUEUE) == -) {
perror("listen");
exit();
} struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
///成功返回非负描述字,出错返回-1
conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if( conn < ) {
perror("connect");
exit();
} char buffer[];
//创建另外一个线程
//std::thread t(thread_task);
//t.join();
//char buf[1024];
//主线程
while() { // memset(buf, 0 ,sizeof(buf));
// if(fgets(buf, sizeof(buf),stdin) != NULL) {
// send(conn, buf, sizeof(buf), 0);
// } memset(buffer, ,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer), );
if(strcmp(buffer, "exit\n") == ) break;
printf("%s", buffer);
//必须要有返回数据, 这样才算一个完整的请求
send(conn, buffer, len , );
}
close(conn);
close(ss);
return ;
}

  局域网聊天TCP客户端:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 7000
#define BUFFER_SIZE 1024 int main()
{
///定义sockfd
int sock_cli = socket(AF_INET,SOCK_STREAM, ); ///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < )
{
perror("connect");
exit();
} char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
send(sock_cli, sendbuf, strlen(sendbuf),); ///发送
if(strcmp(sendbuf,"exit\n")==)
break;
recv(sock_cli, recvbuf, sizeof(recvbuf),); ///接收
fputs(recvbuf, stdout); memset(sendbuf, , sizeof(sendbuf));
memset(recvbuf, , sizeof(recvbuf));
} close(sock_cli);
return ;
}

  


  客户端服务端双向异步聊天源码

  以上的局域网聊天应用有一个很重要的缺点, 服务器只能显示客户端发送的消息, 却无法给客户端发送消息, 这个很尴尬;

  通过使用C中的select()函数, 实现一个异步聊天工具:

  异步聊天服务端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <iostream>
#define PORT 7000
#define QUEUE 20 int main() {
fd_set rfds;
struct timeval tv;
int retval, maxfd;
int ss = socket(AF_INET, SOCK_STREAM, );
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
//printf("%d\n",INADDR_ANY);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-) {
perror("bind");
exit();
}
if(listen(ss, QUEUE) == -) {
perror("listen");
exit();
} struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
///成功返回非负描述字,出错返回-1
int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if( conn < ) {
perror("connect");
exit();
}
while() {
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(conn, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < conn)
maxfd = conn;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...\n");
continue;
}else{
/*客户端发来了消息*/
if(FD_ISSET(conn,&rfds)){
char buffer[];
memset(buffer, ,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer), );
if(strcmp(buffer, "exit\n") == ) break;
printf("%s", buffer);
//send(conn, buffer, len , 0);把数据回发给客户端
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char buf[];
fgets(buf, sizeof(buf), stdin);
//printf("you are send %s", buf);
send(conn, buf, sizeof(buf), );
}
}
}
close(conn);
close(ss);
return ;
}

  异步聊天客户端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 7000
#define BUFFER_SIZE 1024
int main()
{
int sock_cli;
fd_set rfds;
struct timeval tv;
int retval, maxfd; ///定义sockfd
sock_cli = socket(AF_INET,SOCK_STREAM, );
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < )
{
perror("connect");
exit();
} while(){
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(sock_cli, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < sock_cli)
maxfd = sock_cli;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
continue;
}else{
/*服务器发来了消息*/
if(FD_ISSET(sock_cli,&rfds)){
char recvbuf[BUFFER_SIZE];
int len;
len = recv(sock_cli, recvbuf, sizeof(recvbuf),);
printf("%s", recvbuf);
memset(recvbuf, , sizeof(recvbuf));
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char sendbuf[BUFFER_SIZE];
fgets(sendbuf, sizeof(sendbuf), stdin);
send(sock_cli, sendbuf, strlen(sendbuf),); //发送
memset(sendbuf, , sizeof(sendbuf));
}
}
} close(sock_cli);
return ;
}

  局域网内服务端和有限个客户端聊天源码

  以上的局域网聊天只能支持一个用户, 我们还要改改, 必须是支持多用户的聊天室:

  局域网TCP多人聊天服务端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <iostream>
#include <thread>
#define PORT 7000
#define QUEUE 20
int ss;
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int conns[] = {};
int z = ;
void thread_fn() {
//成功返回非负描述字,出错返回-1
int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if( conn < ) {
perror("connect");
exit();
}
//把连接保存到临时数组中;
conns[z] = conn;
z++; fd_set rfds;
struct timeval tv;
int retval, maxfd;
while() {
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(conn, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < conn)
maxfd = conn;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...\n");
continue;
}else{
/*客户端发来了消息*/
if(FD_ISSET(conn,&rfds)){
char buffer[];
memset(buffer, ,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer), );
if(strcmp(buffer, "exit\n") == ) break;
printf("%s", buffer);
//send(conn, buffer, len , 0);把数据回发给客户端
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char buf[];
fgets(buf, sizeof(buf), stdin);
//printf("you are send %s", buf);
for(int i=; i<z; i++) {
send(conns[i], buf, sizeof(buf), );
}
}
}
}
close(conn);
}
void thread_select(int conn) {
}
int main() {
ss = socket(AF_INET, SOCK_STREAM, );
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
//printf("%d\n",INADDR_ANY);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-) {
perror("bind");
exit();
}
if(listen(ss, QUEUE) == -) {
perror("listen");
exit();
}
std::thread t(thread_fn);
std::thread t1(thread_fn);
t.join();
t1.join();
close(ss);
return ;
}

  局域网TCP多人聊天客户端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 7000
#define BUFFER_SIZE 1024
int main()
{
int sock_cli;
fd_set rfds;
struct timeval tv;
int retval, maxfd; ///定义sockfd
sock_cli = socket(AF_INET,SOCK_STREAM, );
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < )
{
perror("connect");
exit();
} while(){
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(sock_cli, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < sock_cli)
maxfd = sock_cli;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
continue;
}else{
/*服务器发来了消息*/
if(FD_ISSET(sock_cli,&rfds)){
char recvbuf[BUFFER_SIZE];
int len;
len = recv(sock_cli, recvbuf, sizeof(recvbuf),);
printf("%s", recvbuf);
memset(recvbuf, , sizeof(recvbuf));
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char sendbuf[BUFFER_SIZE];
fgets(sendbuf, sizeof(sendbuf), stdin);
send(sock_cli, sendbuf, strlen(sendbuf),); //发送
memset(sendbuf, , sizeof(sendbuf));
}
}
} close(sock_cli);
return ;
}

  完美异步聊天服务端和客户端源码

  以上的多客户聊天不是很好, 因为只允许两个客户端连接, 体验非常差, 如果支持无限个客户端聊天的话那该多好啊, 哈哈, 这个也是可以的, 我们只要使用c++的list即可, 它是可以自增的数组(其实算是链表), 引用 头文件<list>即可:

  无限个客户聊天的 服务端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <iostream>
#include <thread>
#include <list> #define PORT 7000
#define IP "127.0.0.1" int s;
struct sockaddr_in servaddr;
socklen_t len;
std::list<int> li; void getConn() {
while(){
int conn = accept(s, (struct sockaddr*)&servaddr, &len);
li.push_back(conn);
printf("%d\n", conn);
}
} void getData() {
struct timeval tv;
tv.tv_sec = ;
tv.tv_usec = ;
while() {
std::list<int>::iterator it;
for(it=li.begin(); it!=li.end(); ++it){
fd_set rfds;
FD_ZERO(&rfds);
int maxfd = ;
int retval = ;
FD_SET(*it, &rfds);
if(maxfd < *it){
maxfd = *it;
}
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select error\n");
}else if(retval == ) {
//printf("not message\n");
}else{
char buf[];
memset(buf, ,sizeof(buf));
int len = recv(*it, buf, sizeof(buf), );
printf("%s", buf);
}
}
sleep(); }
} void sendMess() {
while() {
char buf[];
fgets(buf, sizeof(buf), stdin);
//printf("you are send %s", buf);
std::list<int>::iterator it;
for(it=li.begin(); it!=li.end(); ++it){
send(*it, buf, sizeof(buf), );
}
}
} int main() {
//new socket
s = socket(AF_INET, SOCK_STREAM, );
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = inet_addr(IP);
if(bind(s, (struct sockaddr* ) &servaddr, sizeof(servaddr))==-) {
perror("bind");
exit();
}
if(listen(s, ) == -) {
perror("listen");
exit();
}
len = sizeof(servaddr); //thread : while ==>> accpet
std::thread t(getConn);
t.detach();
//printf("done\n");
//thread : input ==>> send
std::thread t1(sendMess);
t1.detach();
//thread : recv ==>> show
std::thread t2(getData);
t2.detach();
while(){ }
return ;
}

  无限个客户端连接的客户端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 7000
#define BUFFER_SIZE 1024
int main()
{
int sock_cli;
fd_set rfds;
struct timeval tv;
int retval, maxfd; ///定义sockfd
sock_cli = socket(AF_INET,SOCK_STREAM, );
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < )
{
perror("connect");
exit();
} while(){
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(sock_cli, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < sock_cli)
maxfd = sock_cli;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
continue;
}else{
/*服务器发来了消息*/
if(FD_ISSET(sock_cli,&rfds)){
char recvbuf[BUFFER_SIZE];
int len;
len = recv(sock_cli, recvbuf, sizeof(recvbuf),);
printf("%s", recvbuf);
memset(recvbuf, , sizeof(recvbuf));
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char sendbuf[BUFFER_SIZE];
fgets(sendbuf, sizeof(sendbuf), stdin);
send(sock_cli, sendbuf, strlen(sendbuf),); //发送
memset(sendbuf, , sizeof(sendbuf));
}
}
} close(sock_cli);
return ;
}

  局域网通过UDP实现服务端和客户端的通信, UDP的服务端不需要执行listen函数accept函数

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define PORT_SERV 8888
#define BUFF_LEN 256
void udpserv_echo(int s, struct sockaddr* client);
int main() {
int s;
struct sockaddr_in addr_serv, addr_clie;
s = socket(AF_INET, SOCK_DGRAM, );
memset(&addr_serv, , sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
addr_serv.sin_port = htons(PORT_SERV);
bind(s, (struct sockaddr*)&addr_serv, sizeof(addr_serv));
udpserv_echo(s, (struct sockaddr*)&addr_clie);
return ;
}
void udpserv_echo(int s, struct sockaddr* client) {
int n;
char buff[BUFF_LEN];
int len;
//printf("%p\n",&recvfrom);
while() {
socklen_t length = sizeof(client);
n = recvfrom(s, buff, BUFF_LEN, , client, &length);
printf("%s\n", buff);
//strcpy(buff, "nice to see you");
sendto(s, buff, n, , client, len);
}
}

  UDP客户端代码, UDP客户端不需要connect函数, 但是执行sendto的时候需要指定 sockfd描述符:

#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h> #define PORT_SERV 8888
#define BUFF_LEN 256
void udpclient_echo(int s, struct sockaddr* serv) {
char buff[BUFF_LEN];
int len = sizeof(*serv);
while(fgets(buff, BUFF_LEN, stdin)!=NULL) {
sendto(s, buff, BUFF_LEN, , serv, len);
}
}
int main(int argc , char ** argv) {
int s;
struct sockaddr_in addr_serv;
s = socket(AF_INET, SOCK_DGRAM, );
memset(&addr_serv, , sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
//addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
addr_serv.sin_addr.s_addr = inet_addr(argv[]);
addr_serv.sin_port = htons(PORT_SERV);
udpclient_echo(s, (struct sockaddr*)&addr_serv);
return ;
}

  获取当前进程的ID:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
pid_t pid,ppid;
pid = getpid();
ppid = getppid();
printf("pid is %d;\nppid is %d; \n",pid, ppid);
return ;
}

  system语句的使用:

#include <stdlib.h>
#include <stdio.h>
int main(void) {
int ret;
ret = system("ping www.baidu.com");
printf("%d\n", ret);
return ;
}

  C++定时器

  定时器, 这个是c++的语法, c的标准库中没有定时器:

#include <stdio.h>        //printf()
#include <unistd.h> //pause()
#include <signal.h> //signal()
#include <string.h> //memset()
#include <sys/time.h> //struct itimerval, setitimer() static int count = ; void printMes(int signo)
{
printf("Get a SIGALRM, %d counts!\n", ++count);
} int main()
{
int res = ;
struct itimerval tick; signal(SIGALRM, printMes);
memset(&tick, , sizeof(tick)); //Timeout to run first time
tick.it_value.tv_sec = ;
tick.it_value.tv_usec = ; //After first, the Interval time for clock
tick.it_interval.tv_sec = ;
tick.it_interval.tv_usec = ;
setitimer(ITIMER_REAL, &tick, NULL);
//if(setitimer(ITIMER_REAL, &tick, NULL) < 0)
//printf("Set timer failed!\n"); //When get a SIGALRM, the main process will enter another loop for pause()
while()
{
}
return ;

  select的使用,通过select可以实现定时器:

static void sleep_ms(unsigned int secs){
struct timeval tval;
tval.tv_sec=secs/;
tval.tv_usec=(secs*)%;
select(,NULL,NULL,NULL,&tval);
}

  select异步代码

  通过select,实现socket可读或者可写的时候,然后再搞事情:

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
while() {
fd_set rd;
struct timeval tv;
int err; FD_ZERO(&rd);
FD_SET(, &rd); tv.tv_sec = ;
tv.tv_usec = ;
err = select(, &rd, NULL, NULL, &tv);
if(err == -) {
perror("select error()\n");
}else if(err == ) {
printf("no data is avaliable now\n");
}else{
if(FD_ISSET(, &rd)) {
char buf[];
fgets(buf, sizeof(buf), stdin);
printf("%s",buf);
}
}
}
return ;
}

  pthead多线程

  没有参数的多线程 ,假设文件名字为:ph.c ,那么要通过 gcc ph.c -o ph -w -lphread ,进行编译:

#include <stdio.h>
#include <string.h>
#include <pthread.h> void *pfn() {
printf("run\n");
} void main(int argc , char *argv[] ) {
pthread_t pid, pid2;
pthread_create(&pid, NULL, pfn, NULL);
pthread_join(pid, NULL);
}

  pthead多线程编程, 使用pthead实现子程, 并给子程传递参数:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <iostream> void* start(void* args) {
printf("sub thread ; the args is %d\n", *((int *)args));
return NULL;
}
int main(void) {
pthread_t pt;
int ret = -;
int times = ;
int run = ;
ret = pthread_create(&pt, NULL, start, &run);
if(ret != ) {
printf("create error\n");
return ;
}
usleep();
printf("main thread\n");
pthread_join(pt, NULL);
return ;
}

  获取指定网卡的MAC地址和IP:

#include <net/ethernet.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <arpa/inet.h> void getMac(char *MAC, char *str) {
char ifPath[]="/sys/class/net/"; //默认网卡路径
strcat(ifPath , str);
strcat(ifPath ,"/address");
//打开这个设备
FILE *ff = fopen(ifPath,"r");
fread(MAC,, , ff);
fclose(ff);
}
//根据网卡获取ip的通用函数
void getIp(unsigned char *ip, char *itf) {
int fd;
struct ifreq ifr;
in_addr tIP ; fd = socket(AF_INET, SOCK_DGRAM, ); //using ioctl get IP address
ifr.ifr_addr.sa_family = AF_INET;
strcpy(ifr.ifr_name , (char*)itf);
ioctl(fd, SIOCGIFADDR, &ifr); close(fd); tIP =((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
memcpy((char*)ip , &tIP ,sizeof(in_addr));
printf("ip is %s", inet_ntoa(tIP));
} int main(int argc, char *argv[]) {
struct sockaddr_ll device;
char NetInterface[];
strcpy(NetInterface, argv[]);
int index = if_nametoindex ((const char*)NetInterface);
printf("index is %d\n", index); //get MAC, 要设置初始值
char MAC[]={};
char end[] = "";
getMac(MAC, argv[]);
printf("%s\n", MAC); unsigned char ip[];
getIp(ip, argv[]);
printf("\n");
return ;
}

  C, fork语句的使用, fork返回值为0时说明运行在拷贝线程中:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
pid = fork();
if( - == pid ) {
printf("error \n");
}else if( pid == ) {
printf(" fork value %d ; parent id : %d ; fork id : %d\n ", pid, getppid(), getpid());
}else{
printf(" run in parent scope, pid is %d \n", getpid());
}
return ;
}

  通过使用fork,可以简化服务端的代码, 局域网聊天服务端代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h> const int MAX_LINE = ;
const int PORT = ;
const int BACKLOG = ;
const int LISTENQ = ;
const int MAX_CONNECT = ; int main() {
struct sockaddr_in serAddr, cliAddr;
int listenFd, connFd;
pid_t childPid;
char buf[MAX_LINE];
socklen_t client; listenFd = socket(AF_INET, SOCK_STREAM, );
if(listenFd < ){
perror("socket error");
exit(); }
bzero(&serAddr, sizeof(serAddr));
serAddr.sin_family = AF_INET;
serAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serAddr.sin_port = htons(PORT);
if(bind(listenFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < ) {
perror("bind error");
exit();
};
if(listen(listenFd, LISTENQ) < ) {
perror("listen error");
exit();
};
printf("data");
while(true) {
client = sizeof(cliAddr);
connFd = accept(listenFd, (struct sockaddr*)&cliAddr, &client);
if(connFd < ) {
perror("accept error");
exit();
}
childPid =fork();
if(childPid == ) {
close(listenFd);
char buf[MAX_LINE];
while(read(connFd, buf, MAX_LINE) > ) {
printf("data is %s", buf);
memset(buf, ,sizeof(buf));
};
}
}
close(listenFd);
return ;
}

  客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h> const int MAX_LINE = ;
const int PORT = ;
const int BACKLOG = ;
const int LISTENQ = ;
const int MAX_CONNECT = ; int main(int argc , char **argv) {
int sockFd;
struct sockaddr_in serAddr;
if( argc != ) {
perror("args error");
exit();
}
sockFd = socket(AF_INET, SOCK_STREAM, );
if(sockFd < ) {
perror("socket error");
exit();
}
bzero(&serAddr, sizeof(serAddr));
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(PORT);
printf("%s",argv[]);
//serAddr.sin_addr.s_addr = inet_addr(argv[1]);
if(inet_pton(AF_INET , argv[] , &serAddr.sin_addr) < )
{
printf("inet_pton error for %s\n",argv[]);
exit();
}
if(connect(sockFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < ) {
perror("connect error");
exit();
};
char sendLine[MAX_LINE];
while(fgets(sendLine, MAX_LINE, stdin)!=NULL) {
write(sockFd, sendLine, strlen(sendLine));
}
close(sockFd);
return ;
}

  socket服务端:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h> #define QUEUE 10
#define SIZE 256 int main() {
//sock fd
int fd;
struct sockaddr_in saddr, caddr;
fd = socket(AF_INET, SOCK_STREAM, );
if( fd< ){
perror("socket error");
exit();
}
bzero(&saddr , sizeof(saddr));
bzero(&caddr , sizeof(caddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons();
saddr.sin_addr.s_addr = htonl(INADDR_ANY); //bind
int bfd = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if( bfd< ){
perror("bind error");
exit();
}
//listen
int lfd = listen(fd, QUEUE);
if( lfd< ){
perror("listen error");
exit();
}
//accept
socklen_t len = sizeof(caddr);
int conn = accept(fd, (struct sockaddr *)&caddr, &len);
if(conn < ){
perror("conn error");
exit();
}
char buf[SIZE]; while(read(conn, buf, SIZE) > ) {
//read
printf("%s", buf);
bzero(buf, SIZE);
} close(fd);
return ;
}

  socket客户端:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h> #define SIZE 256 int main() {
int fd;
fd = socket(AF_INET, SOCK_STREAM, );
struct sockaddr_in saddr;
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons();
saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int conn;
conn = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr));
if( conn< ) {
perror("error");
exit();
}
char buf[SIZE];
while(fgets(buf, SIZE, stdin)!=NULL) {
printf("%s", buf);
write(fd, buf, SIZE);
bzero(buf, SIZE);
}
return ;
}

  参考

  c++中Socket通信函数之select : http://blog.csdn.net/piaojun_pj/article/details/5991968/

  EOF

作者: NONO
出处:http://www.cnblogs.com/diligenceday/

QQ:287101329

微信:18101055830

linux:C++的socket编程的更多相关文章

  1. Linux学习之socket编程(二)

    Linux学习之socket编程(二) 1.C/S模型——UDP UDP处理模型 由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实 ...

  2. Linux学习之socket编程(一)

    socket编程 socket的概念: 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”就称为socket. 在TCP协议中,建立连接的两个进 ...

  3. Linux下Golang Socket编程原理分析与代码实现

    在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...

  4. Linux 应用开发----socket编程笔记

    Linux socket编程 套接字定义描述 套接字的域 AF_INET ====>IPv4 AF_INET6 ====>IPv6 AF_UNIX ====>unix 域 AF_UP ...

  5. LINUX 下 ipv6 socket 编程

    大家都知道,随着互联网上主机数量的增多,现有的32位IP地址已经不够用了,所以推出了下一代IP地址IPv6,写网络程序的要稍微改变一下现有的网络程序适应IPv6网络是相当容易的事.对于我们来说就是IP ...

  6. Linux下网络socket编程——实现服务器(select)与多个客户端通信

    一.关于socket通信 服务器端工作流程: 调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址绑定 调用listen()函数监听socket() 函数创建的 ...

  7. Linux基础(05)socket编程

    Linux的核心思想之一 "一切皆文件" 内容 , socket在Linux内核的实现的代码及TCP和UDP的实现 网络编程常用头文件: https://blog.csdn.net ...

  8. Linux - 非阻塞socket编程处理EAGAIN错误

            在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这表明你在非阻塞模式下调用 ...

  9. Linux IPC BSD socket编程基础

    头文件 #include<unistd.h> #include <sys/types.h> #include <sys/socket.h> #include< ...

  10. 网络编程学习笔记:linux下的socket编程

    socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, ...

随机推荐

  1. javascript:常用数组操作

    concat()方法 数组和数组的 粘结: var a=[1,2,3,4]; var b=[5,6,7,8]; var c=a.concat(b); console.log(c); // [1,2,3 ...

  2. libxml/HTMLparser.h file

    在导入asihttprequest包时出问题导入了libxml2.dylib,但是却提示libxml/HTMLparser.h file not found,那是因为你的开发环境默认的路径无法找到这个 ...

  3. xcode调试查看变量的值

    对于IPhone开发/XCode的初学者,如何在调试时查看变量的值是很头痛的事情.因为Xcode的expression 经常无法正确显示变量的值.但是强大的GDB可以很方便的帮我们查看变量的值. 当执 ...

  4. 11i and R12 Table Count in Different Module

    Advertisement Module 11i Tables R12 Tables New Tables AR 551 616 118 BOM 264 337 73 GL 186 309 140 A ...

  5. .Net中集合排序

    public class StockQuantity { public StockQuantity(string status, DateTime dateTime, int quantity) { ...

  6. POJ1580 水题,积累!

    [题意简述]:题意非常easy.就是将这两个字符串比較,移动着比較.求出最多的同样的元素个数.然后用题目中所给的公式,写出结果. [分析]:本题要注意的就是for循环的形式.注意积累就可以. 详见代码 ...

  7. Wireshark基本用法 && 过滤规则 && 协议详解

    基本使用: https://www.cnblogs.com/dragonir/p/6219541.html 协议解析: https://www.jianshu.com/p/a384b8e32b67 ( ...

  8. [Hook] 跨进程 Binder 学习指南

    cp from : http://weishu.me/2016/01/12/binder-index-for-newer/ 毫不夸张地说,Binder是Android系统中最重要的特性之一:正如其名“ ...

  9. Spring(AbstractRoutingDataSource)实现动态数据源切换

    转自: http://blog.51cto.com/linhongyu/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中切换数据源,直 ...

  10. 第十章 常用的JVM参数记录

    GC -XX:+PrintGC   打印GC日志 -XX:+PrintGCDetails   打印详细的GC日志 -Xloggc:/var/gc.log   将GC日志打印在根目录的var文件夹下的g ...