linux中socket编程

server的编程
分为6个部分
1.socket
2.bind
3.listen
4.accept
5.read
6.write


socket

socket返回的值是一个文件描述符,SOCKET类型本身也是定义为int的

       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);

domain里面填这些

AF_UNIX, AF_LOCAL  
 Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
       AF_IPX              IPX - Novell protocols
       AF_NETLINK          Kernel user interface device     netlink(7)
       AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
       AF_AX25             Amateur radio AX.25 protocol
       AF_ATMPVC           Access to raw ATM PVCs
       AF_APPLETALK        Appletalk                        ddp(7)
       AF_PACKET           Low level packet interface       packet(7)


在socket创建后,我们还需要为struct sockaddr这个结构体赋值
在这里插入图片描述
在头文件下查找这个结构体包含的内容

struct sockaddr_in {
  __kernel_sa_family_t  sin_family;     /* Address family               */
  __be16                sin_port;       /* Port number                  */
  struct in_addr        sin_addr;       /* Internet address             */

  /* Pad to size of `struct sockaddr'. */
  unsigned char         __pad[__SOCK_SIZE__ - sizeof(short int) -
                        sizeof(unsigned short int) - sizeof(struct in_addr)];
};

/* Internet address. */
struct in_addr {
        __be32  s_addr;
};

在填写结构体内容时,注意转换类型 用到htons,atoi等。 意思是a 码转int型。
h to ns.

     s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&s_addr.sin_addr);
        printf("create socket  successed \n");

type里面写这些

       SOCK_STREAM     Provides sequenced, reliable,  two-way,  connection-based
                       byte streams.  An out-of-band data transmission mechanism
                       may be supported.

       SOCK_DGRAM      Supports datagrams (connectionless,  unreliable  messages
                       of a fixed maximum length).

       SOCK_SEQPACKET  Provides  a sequenced, reliable, two-way connection-based
                       data transmission path for  datagrams  of  fixed  maximum
                       length;  a  consumer is required to read an entire packet
                       with each input system call.

       SOCK_RAW        Provides raw network protocol access.

       SOCK_RDM        Provides a reliable datagram layer that does not  guaran‐
                       tee ordering.

       SOCK_PACKET     Obsolete  and  should  not  be  used in new programs; see
                       packet(7).


bind

       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);



listen

    #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int listen(int sockfd, int backlog);


实战编程:

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{

        int s_fd;
        int c_fd;
        int nread;
        char readbuf[128];
        char msg[128]={0};
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

   memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));
        //1.socket 创建socket
        s_fd = socket( AF_INET ,SOCK_STREAM,0);
//sever send message
        if(s_fd == -1){
                perror("error");
                exit(-1);
        }
//  int socket(int domain, int type, int protocol);


        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&s_addr.sin_addr);
        printf("create socket  successed \n");
        //2.bind 绑定

//int bind(int sockfd, const struct sockaddr *addr,
  //              socklen_t addrlen);
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in ));
        printf("bind   successed \n");
        //3.listen 
//    int listen(int sockfd, int backlog);

        listen(s_fd,10);
        printf("listen ok\n");
        //4.accept

// int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// client  accept message
         int clen = sizeof(struct sockaddr_in);
                //5.read
                c_fd = accept(s_fd,(struct sockaddr *)&s_addr,&clen);
                if(c_fd == -1){
                        perror("accept");

                }
        printf("start while\n");
        while(1){

                printf("get connect %s\n",inet_ntoa(c_addr.sin_addr));

                printf("start fork\n");
//调用线程实现双方同步聊天,用read write交流

                        if(fork()==0){
                                while(1){
                                        //6.write
                                        memset(msg,0,sizeof(msg));//每次初始化缓存,防止内容重复
                                        printf("please input:");
                                        gets(msg);
                                        write(c_fd,msg,strlen(msg));
                                }
                        }


                        while(1){
                                memset(readbuf,0,sizeof(readbuf)); //
                                nread = read(c_fd,readbuf,128);
                                if(nread == -1){

                                        perror("read");
                                }else {
                                        printf("read successed :size :%d text :%s\n",nread,readbuf);
                                }
                        }


        }

        return 0;
}


client部分
1.socket
2.connect
3.read
4.write


connect

     #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
//const struct sockaddr *addr   这用 (struct sockaddr *)强制转换
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{

        int c_fd;
        int nread;
        char readbuf[128];
        char msg[128]={0};
        struct sockaddr_in c_addr;

       memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket
        c_fd = socket( AF_INET ,SOCK_STREAM,0);
//sever send message
        if(c_fd == -1){
                perror("socket");
                exit(-1);
        }
//  int socket(int domain, int type, int protocol);


        c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&c_addr.sin_addr);
        printf("create socket  successed \n");

//    int connect(int sockfd, const struct sockaddr *addr,
  //                 socklen_t addrlen);

         if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr))== -1)//客户端 直接用connect
        {
                perror("connect");
                        exit(-1);
        }
        while(1){

                if(fork()==0){
                        while(1){
                                memset(msg,0,sizeof(msg));
                                printf("input:");
                                gets(msg);
                                write(c_fd,msg,strlen(msg));

                        }
                }

                //5.readd
                while(1){
                        memset(readbuf,0,sizeof(readbuf));
                        nread = read(c_fd,readbuf,128);
                        if(nread == -1){

                                perror("read");
                        }else {
                                printf("read successed :size :%d text :%s\n",nread,readbuf);
                        }
                }

        }
        //6.write


        printf("connect  successed \n");
        return 0;
}
                    

功能进阶:实现多方聊天
建立一个mark计数符, 进行每三秒中向客户端发送一个id来表示连接

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{
        int mark =0 ;
        int s_fd;
        int c_fd;
        int nread;
        char readbuf[128];
        char msg[128]={0};
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket
        s_fd = socket( AF_INET ,SOCK_STREAM,0);
//sever send message
        if(s_fd == -1){
                perror("error");
                exit(-1);
        }
//  int socket(int domain, int type, int protocol);


        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&s_addr.sin_addr);
        printf("create socket  successed \n");
        //2.bind

//int bind(int sockfd, const struct sockaddr *addr,
  //              socklen_t addrlen);
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in ));
        printf("bind   successed \n");
        //3.listen
//    int listen(int sockfd, int backlog);
 listen(s_fd,10);
        printf("listen ok\n");
        //4.accept

// int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// client  accept message

        int clen = sizeof(struct sockaddr_in);
                //5.read
        while(1){

                c_fd = accept(s_fd,(struct sockaddr *)&s_addr,&clen);
                if(c_fd == -1){
                        perror("accept");

                }
                mark++;

                printf("get connect %s\n",inet_ntoa(c_addr.sin_addr));

                if(fork() == 0){
                        if(fork()==0){
                                while(1){
                                        //6.write
                                        sprintf(msg,"welcome NO.%d client\n",mark);
                                        write(c_fd,msg,strlen(msg));
                                        sleep(3);

                                }
                        }


                        while(1){
                                memset(readbuf,0,sizeof(readbuf));
                                nread = read(c_fd,readbuf,128);
                                if(nread == -1){

                                        perror("read");
                                }else {
                                        printf("read successed :size :%d text :%s\n",nread,readbuf);
                                }
                        }

                }
        }

        return 0;
}

在这里插入图片描述

结合gtk 图形界面

client 客户端


#include <gtk/gtk.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
 
#define OURPORT 4321
gint sd;
struct sockaddr_in s_in;
gchar username[64];
gchar buf[1024];
gchar get_buf[1048];
gboolean isconnected = FALSE;
 
static GtkWidget *text;
static GtkTextBuffer *buffer; //缓存
static GtkWidget *message_entry;//消息
static GtkWidget *name_entry;//用户名
static GtkWidget *login_button;//登入按钮
 
void get_message()
{
    GtkTextIter iter;
    gchar get_buf[1024];
    gchar buf[1024];
    gint num = -1;
    while(num = recv(sd, buf, 1024,0)) { //接收  s_fd 的消息到缓存
        if (num == -1 || num == 0) break;//未读取到消息 break
        sprintf(get_buf, "%s", buf);
        gdk_threads_enter();
        gtk_text_buffer_get_end_iter(buffer, &iter);
        gtk_text_buffer_insert(buffer, &iter, get_buf, -1);
        gdk_threads_leave();
    }
}
 
gboolean do_connect_run()
{
    struct hostent *host;
    GtkTextIter iter;
    gint slen;
    sd = socket(AF_INET, SOCK_STREAM, 0); //socket 编程的文件符 int s_fd
    if (sd < 0) {
    // gtk_text_buffer_get_start_iter(Send_buffer,&start);/*得到当前文本区域的起始位置*/ 
   // gtk_text_buffer_get_end_iter(Send_buffer,&end);/*得到当前文本区域的结束位置*/ 
    //应该类似读写文件时的光标操作?
        gtk_text_buffer_get_end_iter(buffer, &iter);
        gtk_text_buffer_insert(buffer, &iter, "打开套接字时出错!\n", -1);
        ///*插入文本到缓冲区*/ 
        return FALSE;
    }

    //为server的结构体赋值, 具体结构体参数可以去头文件里查询
    s_in.sin_family = AF_INET;
    //地址协议  man手册里面有具体介绍
    host=gethostbyname("127.0.0.1");
    //本地IP地址,127.0.0.1为默认(类似于中文的“我自己”),192.168.x.x为真实地址
    //需要时可 修改ip地址 为了运行
    s_in.sin_addr=*((struct in_addr *)host->h_addr);
    //存放地址信息
    s_in.sin_port = htons(OURPORT);
    //端口  socket编程要两个参数, 一个ip 一个端口  端口要大一点 不然会有影响  
    slen = sizeof(s_in);//结构体大小

    //int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    //  const struct sockaddr *addr 这里需要强转struct类型
    //函数返回值 成功返回0,失败返回-1,设置errno
    if (connect(sd, (struct sockaddr*)&s_in, slen) < 0) {
        gtk_text_buffer_get_end_iter(buffer, &iter);
        gtk_text_buffer_insert(buffer, &iter, "连接服务器时出错!\n", -1);
        //同上 插入一段文字到缓冲区
        return FALSE;
    }
    else {
        gtk_text_buffer_get_end_iter(buffer, &iter);
        gtk_text_buffer_insert(buffer, &iter, username, -1);
        gtk_text_buffer_get_end_iter(buffer, &iter);
        gtk_text_buffer_insert(buffer, &iter, "成功与服务器连接...\n", -1);
        //成功连接
        //将用户名写入 s_fd  发给服务器
        write(sd, username, 64);
        isconnected = TRUE;
        return TRUE;//检测 connect    返回bool  这个函数用来判定是否正确连接服务器
    }
}
void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer data)
{
    sprintf(username, "guest");
    if(do_connect_run() == TRUE) {
        gtk_widget_set_sensitive(login_button, FALSE);
        g_thread_create((GThreadFunc)get_message, NULL, FALSE, NULL);
    }
    gtk_widget_destroy(widget);
}
void on_button_clicked(GtkButton *button, gpointer data)
{
    const gchar *name;
    name = gtk_entry_get_text(GTK_ENTRY(name_entry));//获取用户名
    sprintf(username, "%s", name);//将name 输入到username
    if (do_connect_run()) {
        gtk_widget_set_sensitive(login_button, FALSE);
        g_thread_create((GThreadFunc)get_message, NULL, FALSE, NULL);
    }
    gtk_widget_destroy(GTK_WIDGET(data));
}
void create_win()
{   //创建 登入 图形界面  为用户名 赋值
    GtkWidget *win, *vbox;
    GtkWidget *button;
    
    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);//创建新窗口在最上层
    g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(on_destroy), NULL);

    gtk_window_set_title(GTK_WINDOW(win), "输入用户名");
    gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);//设置窗口位置
    gtk_container_set_border_width(GTK_CONTAINER(win), 10);//设置容器参数
    gtk_window_set_modal(GTK_WINDOW(win), TRUE);
    //设置窗口模式
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(win), vbox);

    name_entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(vbox), name_entry, TRUE, TRUE, 5);
    //用户名 输入文本框
    button = gtk_button_new_from_stock(GTK_STOCK_OK);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_button_clicked), win);
    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5);
    // 按钮 跳转
    gtk_widget_show_all(win);
}
void on_send(GtkButton *button, gpointer data)
{
    const gchar *message;
    if (isconnected == FALSE) return; //没连接 退出
    message = gtk_entry_get_text(GTK_ENTRY(message_entry));
    if (g_strcmp0(message, "") == 0) return; //消息为空 退出
    sprintf(buf, "%s", message);
    send(sd, buf, 1024,0);// 缓冲区内容发送到fd
    gtk_entry_set_text(GTK_ENTRY(message_entry), "");//消息框 清空!
} 
void on_login(GtkWidget *button, gpointer data)
{
    create_win();
}
void on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
    close(sd);
    gtk_main_quit();//关闭 s_fd   gtk图形界面退出!
}
int main(int argc, char *argv[])
{
    GtkWidget *window;//窗口创建
    GtkWidget *vbox, *hbox, *button, *label, *view;
//消息框, 按钮, 标签

    if (!g_thread_supported()) {
        g_thread_init(NULL);
    }
    else {
        g_print("thread not supported\n");
    }//创建线程

    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(on_delete_event), NULL);
// GTK+2.0中利用信号/回调函数机制来处理窗口外部传来的事件、消息或信号,    调用函数!!!
    gtk_window_set_title(GTK_WINDOW(window), "客户端");//窗口标题命名
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    //设置窗口位置  在中间
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    //为容器在窗口中设置空间
//GtkWidget *   gtk_vbox_new (gboolean homogeneous,    gint spacing); 
//homogeneous是一个布尔值,为TRUE时,强制盒中的构件都占用相同大小的空间,不管每个空间的大小
    vbox = gtk_vbox_new(FALSE, 0);//定义垂直容器创建
    //void gtk_container_add(GtkContainer *container, GtkWidget *widget);
    //container:容纳控件的容器 ,widget:要添加的控件
    gtk_container_add(GTK_CONTAINER(window), vbox);//添加容器

    hbox = gtk_hbox_new(FALSE, 0);//同上  表示水平容器

    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
    把 hbox 安排在 vbox 内
    label = gtk_label_new("点击登录按钮连接服务器");//标签,提示用户操作
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
    //同上 将label安排在hbox内
    login_button = gtk_button_new_with_label("登录");//登入按钮
    gtk_box_pack_start(GTK_BOX(hbox), login_button, FALSE, FALSE, 5);
    //将登入button安排在hbox中
    g_signal_connect(G_OBJECT(login_button), "clicked", G_CALLBACK(on_login), NULL);
    //g_signal_connect(按钮,"单击",G_CALLBACK(& MainWindow: nButtonClicked),NULL);
    // 收到点击按钮信号,触发   login 函数

    view = gtk_scrolled_window_new(NULL, NULL);//产生一个有卷轴的窗口
    //有些元件預設並沒有捲軸,當視窗或父元件無法顯示其大小時,只會顯示部份區域,
    //但不會出現捲軸,如果您希望這類元件可以出現捲軸,則可以使用GtkScrolledWindow
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(view), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    //名称:: gtk_scrolled_window_set_policy 功能: 设置滚动条出现的方式 
    
    text = gtk_text_view_new();
    gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 5);
    gtk_container_add(GTK_CONTAINER(view), text);
    //生成一个输入框 放在卷轴窗口内?

    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
    //名称::gtk_text_view_get_buffer
//功能:获得文本框的缓冲区
//函数原形:GtkTextBuffer* gtk_text_view_get_buffer (GtkTextView *text_view);
    //
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
   //继续生成一个水平容器放在vbox 垂直容器里面
    label = gtk_label_new("输入信息:");
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
   //生成一个label标签: 输入信息    用来提示用户
    message_entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(hbox), message_entry, FALSE, FALSE, 5);
    //消息输入窗口
    button = gtk_button_new_with_label("发送");
    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_send), NULL);
    //生成发送按钮

    gtk_widget_show_all(window);//显示所有容器中的控件
    
    gdk_threads_enter();
    gtk_main();
    gdk_threads_leave();
    //  调用进程更新界面
    return TRUE;
}


服务器端代码实战!


#include <glib.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
 
#define OURPORT 4321
#define MAX_USERS 8
 
struct _client
{
    gint sd;
    gboolean in_use;
    gchar name[64];
    gchar buf[1024];
};
typedef struct _client client;
//定义存放 客户端消息的结构体
client user[MAX_USERS];
 //客户端 变量声明   限制最大在线数量
void do_service(gpointer id)
{
    gint j;
    gchar tobuf[1024] = {0};
    gint num = -1;
    while(num = recv(user[GPOINTER_TO_INT(id)].sd, user[GPOINTER_TO_INT(id)].buf, 1024,0)) {
        if (num == -1 || num == 0) break;
        sprintf(tobuf, "%s:%s\n", user[GPOINTER_TO_INT(id)].name, user[GPOINTER_TO_INT(id)].buf);
        // 把用户 用户名字  用户信息 写到缓存中
        for(j = 0; j < MAX_USERS; j++) {
            if (user[j].in_use) {
                send(user[j].sd, tobuf, 1024,0);
                printf("%s", tobuf);
            }
        }//遍历用户!! 输出 缓存
    }
    user[GPOINTER_TO_INT(id)].in_use = FALSE;
    close(user[GPOINTER_TO_INT(id)].sd);
}
int main(int argc, char *argv[])
{
    gint sd, newsd;
    struct sockaddr_in *sin;
    gint slen;
    gint count = 0;
    gint flags;
    gchar buf[1024];
    gchar tobuf[1024];
    gint length, i, j;
    if (!g_thread_supported()) {
        g_thread_init(NULL);
    }
    else {
        g_print("thread not supported\n");
    }
    sd = socket(AF_INET, SOCK_STREAM, 0);
    // 服务器 socket文件s_fd 变量声明 
    if (sd == -1) {
        g_print("create socket error!\n");
        return -1;
    }
    sin = g_new(struct sockaddr_in, 1);
    sin->sin_family = AF_INET;
    sin->sin_addr.s_addr=inet_addr("127.0.0.1");
    sin->sin_port = htons(OURPORT);
    //socket服务器结构体赋值  ,   具体内容 去头文件中查询
    slen = sizeof(struct sockaddr_in);
    if (bind(sd, (struct sockaddr*)sin, slen) < 0) {
        g_print("bind error!\n");
        return -1;
    }
    //绑定 套字节  将服务器 与 127.0.0.1 和端口 ourport 绑定  
    //例如  ./server 127.0.0.1 8989
    if (listen(sd, 8) < 0) {
        g_print("listen error!\n");
        return -1;
    }
    //监听,   定义服务器监听的个数
    for (i = 0; i < MAX_USERS; i++) {
        user[i].in_use = FALSE;
    }
    flags = fcntl(sd, F_GETFL);
    //fcntl是计算机中的一种函数,通过fcntl可以改变已打开的文件性质。
    //fcntl针对描述符提供控制。
    //参数fd是被参数cmd操作的描述符。针对cmd的值,fcntl能够接受第三个参数int arg。进行阻塞

    fcntl(sd, F_SETFL, flags &~O_NDELAY);
    for(;;) {
        newsd = accept(sd, (struct sockaddr*)sin, (socklen_t *)&slen);
        //accept   函数   服务器接收客户端的connect请求!
        if (newsd == -1) {
            g_print("accept error!\n");
            break;
        }
        else {
            if (count >= MAX_USERS) {
                sprintf(buf, "用户数量过多服务器不能通讯。\n");
                write(newsd, buf, 1024);
                close(newsd);
            }//用户数 检测
            else {
                flags = fcntl(user[i].sd, F_GETFL);
                fcntl(user[i].sd, F_SETFL, O_NONBLOCK);
                user[count].sd = newsd;
                user[count].in_use = TRUE;
                read(newsd, user[count].name, 64);
                g_thread_create((GThreadFunc)do_service, (gpointer)count, TRUE, NULL);
                count++;
            }
            
        }
    }
    close(sd);
    g_free(sin);
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值